X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=input_utils.py;h=5e36db1ba853884636a2df7a5007004aa086760b;hb=711a9fd699f7c724f0aab7c1c43511cfbf7b2281;hp=e0b457d5a0e73ffc43d3d83ff09228328e6a641e;hpb=b29be4f1750fd20bd2eada88e751dfae85817882;p=python_utils.git diff --git a/input_utils.py b/input_utils.py index e0b457d..5e36db1 100644 --- a/input_utils.py +++ b/input_utils.py @@ -1,34 +1,35 @@ #!/usr/bin/env python3 +# © Copyright 2021-2022, Scott Gasch + """Utilities related to user input.""" import logging import signal import sys -from typing import List +from typing import List, Optional import readchar # type: ignore import exceptions - logger = logging.getLogger(__file__) def single_keystroke_response( - valid_responses: List[str], + valid_responses: Optional[List[str]], # None = accept anything *, prompt: str = None, default_response: str = None, timeout_seconds: int = None, -) -> str: +) -> Optional[str]: # None if timeout w/o keystroke """Get a single keystroke response to a prompt.""" def _handle_timeout(signum, frame) -> None: raise exceptions.TimeoutError() def _single_keystroke_response_internal( - valid_responses: List[str], timeout_seconds=None + valid_responses: Optional[List[str]], timeout_seconds: int = None ) -> str: os_special_keystrokes = [3, 26] # ^C, ^Z if timeout_seconds is not None: @@ -38,8 +39,8 @@ def single_keystroke_response( try: while True: response = readchar.readchar() - logger.debug(f'Keystroke: {ord(response)}') - if response in valid_responses: + logger.debug('Keystroke: 0x%x', ord(response)) + if not valid_responses or response in valid_responses: break if ord(response) in os_special_keystrokes: break @@ -48,30 +49,40 @@ def single_keystroke_response( if timeout_seconds is not None: signal.alarm(0) + response = None if prompt is not None: print(prompt, end="") sys.stdout.flush() try: - response = _single_keystroke_response_internal( - valid_responses, timeout_seconds - ) + response = _single_keystroke_response_internal(valid_responses, timeout_seconds) if ord(response) == 3: raise KeyboardInterrupt('User pressed ^C in input_utils.') except exceptions.TimeoutError: if default_response is not None: response = default_response - if prompt is not None: + if prompt and response: print(response) return response -def yn_response(prompt: str = None, *, timeout_seconds=None) -> str: +def yn_response(prompt: str = None, *, timeout_seconds=None) -> Optional[str]: """Get a Y/N response to a prompt.""" - return single_keystroke_response( + yn = single_keystroke_response( ["y", "n", "Y", "N"], prompt=prompt, timeout_seconds=timeout_seconds - ).lower() + ) + if yn: + yn = yn.lower() + return yn + + +def press_any_key( + prompt: str = "Press any key to continue...", *, timeout_seconds=None +) -> Optional[str]: + """Press any key to continue...""" + + return single_keystroke_response(None, prompt=prompt, timeout_seconds=timeout_seconds) def keystroke_helper() -> None: