Skip to content

Commit 2b67672

Browse files
committed
implement posix ContextManager
1 parent 59d739f commit 2b67672

1 file changed

Lines changed: 32 additions & 5 deletions

File tree

readchar/_posix_read.py

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import sys
22
import termios
3+
from copy import copy
4+
from select import select
35

46
from ._config import config
57

@@ -12,28 +14,53 @@ def __init__(self, cfg: config = None) -> None:
1214
self.config = cfg if cfg is not None else config
1315

1416
def __enter__(self) -> "ReadChar":
15-
raise NotImplementedError("ToDo")
17+
self.fd = sys.stdin.fileno()
18+
term = termios.tcgetattr(self.fd)
19+
self.old_settings = copy(term)
20+
term[3] &= ~(termios.ICANON | termios.ECHO | termios.IGNBRK | termios.BRKINT)
21+
termios.tcsetattr(self.fd, termios.TCSAFLUSH, term)
1622
return self
1723

1824
def __exit__(self, type, value, traceback) -> None:
19-
raise NotImplementedError("ToDo")
25+
termios.tcsetattr(self.fd, termios.TCSADRAIN, self.old_settings)
2026

2127
@property
2228
def key_waiting(self) -> bool:
2329
"""True if a key has been pressed and is waiting to be read. False if not."""
24-
raise NotImplementedError("ToDo")
30+
return sys.stdin in select([sys.stdin], [], [], 0)[0]
2531

2632
def char(self) -> str:
2733
"""Reads a singel char from the input stream and returns it as a string of
2834
length one. Does not require the user to press ENTER."""
29-
raise NotImplementedError("ToDo")
35+
return sys.stdin.read(1)
3036

3137
def key(self) -> str:
3238
"""Reads a keypress from the input stream and returns it as a string. Keypressed
3339
consisting of multiple characterrs will be read completly and be returned as a
3440
string matching the definitions in `key.py`.
3541
Does not require the user to press ENTER."""
36-
raise NotImplementedError("ToDo")
42+
c1 = self.char()
43+
44+
if c1 in self.config.INTERRUPT_KEYS:
45+
raise KeyboardInterrupt
46+
47+
if c1 != "\x1B":
48+
return c1
49+
50+
c2 = self.char()
51+
if c2 not in "\x4F\x5B":
52+
return c1 + c2
53+
54+
c3 = self.char()
55+
if c3 not in "\x31\x32\x33\x35\x36":
56+
return c1 + c2 + c3
57+
58+
c4 = self.char()
59+
if c4 not in "\x30\x31\x33\x34\x35\x37\x38\x39":
60+
return c1 + c2 + c3 + c4
61+
62+
c5 = self.char()
63+
return c1 + c2 + c3 + c4 + c5
3764

3865

3966
# Initially taken from:

0 commit comments

Comments
 (0)