|
1 | 1 | import msvcrt |
| 2 | +import signal |
2 | 3 |
|
| 4 | +from . import _win_key as key |
3 | 5 | from ._config import config |
4 | 6 |
|
5 | 7 |
|
6 | 8 | class ReadChar: |
7 | 9 | """A ContextManager allowing for keypress collection without requiering the user to |
8 | 10 | confirm presses with ENTER. Can be used non-blocking while inside the context.""" |
9 | 11 |
|
| 12 | + @staticmethod |
| 13 | + def __silent_CTRL_C_callback(signum, frame): |
| 14 | + msvcrt.ungetch(key.CTRL_C.encode("ascii")) |
| 15 | + |
10 | 16 | def __init__(self, cfg: config = None) -> None: |
11 | 17 | self.config = cfg if cfg is not None else config |
12 | 18 |
|
13 | 19 | def __enter__(self) -> "ReadChar": |
14 | | - raise NotImplementedError("ToDo") |
| 20 | + self.__org_SIGBREAK_handler = signal.getsignal(signal.SIGBREAK) |
| 21 | + self.__org_SIGINT_handler = signal.getsignal(signal.SIGINT) |
| 22 | + signal.signal(signal.SIGBREAK, signal.default_int_handler) |
| 23 | + signal.signal(signal.SIGINT, ReadChar.__silent_CTRL_C_callback) |
15 | 24 | return self |
16 | 25 |
|
17 | 26 | def __exit__(self, type, value, traceback) -> None: |
18 | | - raise NotImplementedError("ToDo") |
| 27 | + signal.signal(signal.SIGBREAK, self.__org_SIGBREAK_handler) |
| 28 | + signal.signal(signal.SIGINT, self.__org_SIGINT_handler) |
19 | 29 |
|
20 | 30 | @property |
21 | 31 | def key_waiting(self) -> bool: |
22 | 32 | """True if a key has been pressed and is waiting to be read. False if not.""" |
23 | | - raise NotImplementedError("ToDo") |
| 33 | + return msvcrt.kbhit() |
24 | 34 |
|
25 | 35 | def char(self) -> str: |
26 | 36 | """Reads a singel char from the input stream and returns it as a string of |
27 | 37 | length one. Does not require the user to press ENTER.""" |
28 | | - raise NotImplementedError("ToDo") |
| 38 | + return msvcrt.getch().decode("latin1") |
29 | 39 |
|
30 | 40 | def key(self) -> str: |
31 | 41 | """Reads a keypress from the input stream and returns it as a string. Keypressed |
32 | 42 | consisting of multiple characterrs will be read completly and be returned as a |
33 | 43 | string matching the definitions in `key.py`. |
34 | 44 | Does not require the user to press ENTER.""" |
35 | | - raise NotImplementedError("ToDo") |
| 45 | + c = self.char() |
| 46 | + |
| 47 | + if c in self.config.INTERRUPT_KEYS: |
| 48 | + raise KeyboardInterrupt |
| 49 | + |
| 50 | + # if it is a normal character: |
| 51 | + if c not in "\x00\xe0": |
| 52 | + return c |
| 53 | + |
| 54 | + # if it is a special key, read second half: |
| 55 | + return "\x00" + self.char() |
36 | 56 |
|
37 | 57 |
|
38 | 58 | def readchar() -> str: |
|
0 commit comments