def add_hotkey(hotkey, callback, args=(), suppress=False, timeout=<NUM_LIT:1>, trigger_on_release=False):
if args:<EOL><INDENT>callback = lambda callback=callback: callback(*args)<EOL><DEDENT>_listener.start_if_necessary()<EOL>steps = parse_hotkey_combinations(hotkey)<EOL>event_type = KEY_UP if trigger_on_release else KEY_DOWN<EOL>if len(steps) == <NUM_LIT:1>:<EOL><INDENT>handler = lambda e: (event_type == KEY_DOWN and e.event_type == KEY_UP and e.scan_code in _logically_pressed_keys) or (event_type == e.event_type and callback())<EOL>remove_step = _add_hotkey_step(handler, steps[<NUM_LIT:0>], suppress)<EOL>def remove_():<EOL><INDENT>remove_step()<EOL>del _hotkeys[hotkey]<EOL>del _hotkeys[remove_]<EOL>del _hotkeys[callback]<EOL><DEDENT>_hotkeys[hotkey] = _hotkeys[remove_] = _hotkeys[callback] = remove_<EOL>return remove_<EOL><DEDENT>state = _State()<EOL>state.remove_catch_misses = None<EOL>state.remove_last_step = None<EOL>state.suppressed_events = []<EOL>state.last_update = float('<STR_LIT>')<EOL>def catch_misses(event, force_fail=False):<EOL><INDENT>if (<EOL>event.event_type == event_type<EOL>and state.index<EOL>and event.scan_code not in allowed_keys_by_step[state.index]<EOL>) or (<EOL>timeout<EOL>and _time.monotonic() - state.last_update >= timeout<EOL>) or force_fail: <EOL><INDENT>state.remove_last_step()<EOL>for event in state.suppressed_events:<EOL><INDENT>if event.event_type == KEY_DOWN:<EOL><INDENT>press(event.scan_code)<EOL><DEDENT>else:<EOL><INDENT>release(event.scan_code)<EOL><DEDENT><DEDENT>del state.suppressed_events[:]<EOL>index = <NUM_LIT:0><EOL>set_index(<NUM_LIT:0>)<EOL><DEDENT>return True<EOL><DEDENT>def set_index(new_index):<EOL><INDENT>state.index = new_index<EOL>if new_index == <NUM_LIT:0>:<EOL><INDENT>state.remove_catch_misses = lambda: None<EOL><DEDENT>elif new_index == <NUM_LIT:1>:<EOL><INDENT>state.remove_catch_misses()<EOL>state.remove_catch_misses = hook(catch_misses, suppress=True)<EOL><DEDENT>if new_index == len(steps) - <NUM_LIT:1>:<EOL><INDENT>def handler(event):<EOL><INDENT>if event.event_type == KEY_UP:<EOL><INDENT>remove()<EOL>set_index(<NUM_LIT:0>)<EOL><DEDENT>accept = event.event_type == event_type and callback() <EOL>if accept:<EOL><INDENT>return catch_misses(event, force_fail=True)<EOL><DEDENT>else:<EOL><INDENT>state.suppressed_events[:] = [event]<EOL>return False<EOL><DEDENT><DEDENT>remove = _add_hotkey_step(handler, steps[state.index], suppress)<EOL><DEDENT>else:<EOL><INDENT>def handler(event, new_index=state.index+<NUM_LIT:1>):<EOL><INDENT>if event.event_type == KEY_UP:<EOL><INDENT>remove()<EOL>set_index(new_index)<EOL><DEDENT>state.suppressed_events.append(event)<EOL>return False<EOL><DEDENT>remove = _add_hotkey_step(handler, steps[state.index], suppress)<EOL><DEDENT>state.remove_last_step = remove<EOL>state.last_update = _time.monotonic()<EOL>return False<EOL><DEDENT>set_index(<NUM_LIT:0>)<EOL>allowed_keys_by_step = [<EOL>set().union(*step)<EOL>for step in steps<EOL>]<EOL>def remove_():<EOL><INDENT>state.remove_catch_misses()<EOL>state.remove_last_step()<EOL>del _hotkeys[hotkey]<EOL>del _hotkeys[remove_]<EOL>del _hotkeys[callback]<EOL><DEDENT>_hotkeys[hotkey] = _hotkeys[remove_] = _hotkeys[callback] = remove_<EOL>return remove_<EOL>
Invokes a callback every time a hotkey is pressed. The hotkey must
be in the format `ctrl+shift+a, s`. This would trigger when the user holds
ctrl, shift and "a" at once, releases, and then presses "s". To represent
literal commas, pluses, and spaces, use their names ('comma', 'plus',
'space').

- `args` is an optional list of arguments to passed to the callback during
each invocation.
- `suppress` defines if successful triggers should block the keys from being
sent to other programs.
- `timeout` is the amount of seconds allowed to pass between key presses.
- `trigger_on_release` if true, the callback is invoked on key release instead
of key press.

The event handler function is returned. To remove a hotkey call
`remove_hotkey(hotkey)` or `remove_hotkey(handler)`.
before the hotkey state is reset.

Note: hotkeys are activated when the last key is *pressed*, not released.
Note: the callback is executed in a separate thread, asynchronously. For an
example of how to use a callback synchronously, see `wait`.

Examples:

    # Different but equivalent ways to listen for a spacebar key press.
    add_hotkey(' ', print, args=['space was pressed'])
    add_hotkey('space', print, args=['space was pressed'])
    add_hotkey('Space', print, args=['space was pressed'])
    # Here 57 represents the keyboard code for spacebar; so you will be
    # pressing 'spacebar', not '57' to activate the print function.
    add_hotkey(57, print, args=['space was pressed'])

    add_hotkey('ctrl+q', quit)
    add_hotkey('ctrl+alt+enter, space', some_callback)