User input abstraction