Skip to content

Commit 59d739f

Browse files
committed
implement windows ContextManager
1 parent aa55140 commit 59d739f

1 file changed

Lines changed: 25 additions & 5 deletions

File tree

readchar/_win_read.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,58 @@
11
import msvcrt
2+
import signal
23

4+
from . import _win_key as key
35
from ._config import config
46

57

68
class ReadChar:
79
"""A ContextManager allowing for keypress collection without requiering the user to
810
confirm presses with ENTER. Can be used non-blocking while inside the context."""
911

12+
@staticmethod
13+
def __silent_CTRL_C_callback(signum, frame):
14+
msvcrt.ungetch(key.CTRL_C.encode("ascii"))
15+
1016
def __init__(self, cfg: config = None) -> None:
1117
self.config = cfg if cfg is not None else config
1218

1319
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)
1524
return self
1625

1726
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)
1929

2030
@property
2131
def key_waiting(self) -> bool:
2232
"""True if a key has been pressed and is waiting to be read. False if not."""
23-
raise NotImplementedError("ToDo")
33+
return msvcrt.kbhit()
2434

2535
def char(self) -> str:
2636
"""Reads a singel char from the input stream and returns it as a string of
2737
length one. Does not require the user to press ENTER."""
28-
raise NotImplementedError("ToDo")
38+
return msvcrt.getch().decode("latin1")
2939

3040
def key(self) -> str:
3141
"""Reads a keypress from the input stream and returns it as a string. Keypressed
3242
consisting of multiple characterrs will be read completly and be returned as a
3343
string matching the definitions in `key.py`.
3444
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()
3656

3757

3858
def readchar() -> str:

0 commit comments

Comments
 (0)