-
-
Notifications
You must be signed in to change notification settings - Fork 43
Expand file tree
/
Copy pathtermbox.py
More file actions
executable file
·294 lines (239 loc) · 6.42 KB
/
Copy pathtermbox.py
File metadata and controls
executable file
·294 lines (239 loc) · 6.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
"""Implementation of Termbox Python API in tdl.
See README.md for details.
"""
import tdl
"""
Implementation status:
[ ] tdl.init() needs a window, made 132x60
[ ] Termbox.close() is not implemented, does nothing
[ ] poll_event needs review, because it does not
completely follows the original logic
[ ] peek is stubbed, but not implemented
[ ] not all keys/events are mapped
"""
class TermboxException(Exception):
def __init__(self, msg) -> None:
self.msg = msg
def __str__(self) -> str:
return self.msg
_instance = None
# keys ----------------------------------
KEY_F1 = 0xFFFF - 0
KEY_F2 = 0xFFFF - 1
KEY_F3 = 0xFFFF - 2
KEY_F4 = 0xFFFF - 3
KEY_F5 = 0xFFFF - 4
KEY_F6 = 0xFFFF - 5
KEY_F7 = 0xFFFF - 6
KEY_F8 = 0xFFFF - 7
KEY_F9 = 0xFFFF - 8
KEY_F10 = 0xFFFF - 9
KEY_F11 = 0xFFFF - 10
KEY_F12 = 0xFFFF - 11
KEY_INSERT = 0xFFFF - 12
KEY_DELETE = 0xFFFF - 13
KEY_PGUP = 0xFFFF - 16
KEY_PGDN = 0xFFFF - 17
KEY_MOUSE_LEFT = 0xFFFF - 22
KEY_MOUSE_RIGHT = 0xFFFF - 23
KEY_MOUSE_MIDDLE = 0xFFFF - 24
KEY_MOUSE_RELEASE = 0xFFFF - 25
KEY_MOUSE_WHEEL_UP = 0xFFFF - 26
KEY_MOUSE_WHEEL_DOWN = 0xFFFF - 27
KEY_CTRL_TILDE = 0x00
KEY_CTRL_2 = 0x00
KEY_CTRL_A = 0x01
KEY_CTRL_B = 0x02
KEY_CTRL_C = 0x03
KEY_CTRL_D = 0x04
KEY_CTRL_E = 0x05
KEY_CTRL_F = 0x06
KEY_CTRL_G = 0x07
KEY_BACKSPACE = 0x08
KEY_CTRL_H = 0x08
KEY_TAB = 0x09
KEY_CTRL_I = 0x09
KEY_CTRL_J = 0x0A
KEY_CTRL_K = 0x0B
KEY_CTRL_L = 0x0C
KEY_ENTER = 0x0D
KEY_CTRL_M = 0x0D
KEY_CTRL_N = 0x0E
KEY_CTRL_O = 0x0F
KEY_CTRL_P = 0x10
KEY_CTRL_Q = 0x11
KEY_CTRL_R = 0x12
KEY_CTRL_S = 0x13
KEY_CTRL_T = 0x14
KEY_CTRL_U = 0x15
KEY_CTRL_V = 0x16
KEY_CTRL_W = 0x17
KEY_CTRL_X = 0x18
KEY_CTRL_Y = 0x19
KEY_CTRL_Z = 0x1A
# -- mapped to tdl
KEY_HOME = "HOME"
KEY_END = "END"
KEY_ARROW_UP = "UP"
KEY_ARROW_DOWN = "DOWN"
KEY_ARROW_LEFT = "LEFT"
KEY_ARROW_RIGHT = "RIGHT"
KEY_ESC = "ESCAPE"
# /--
KEY_CTRL_LSQ_BRACKET = 0x1B
KEY_CTRL_3 = 0x1B
KEY_CTRL_4 = 0x1C
KEY_CTRL_BACKSLASH = 0x1C
KEY_CTRL_5 = 0x1D
KEY_CTRL_RSQ_BRACKET = 0x1D
KEY_CTRL_6 = 0x1E
KEY_CTRL_7 = 0x1F
KEY_CTRL_SLASH = 0x1F
KEY_CTRL_UNDERSCORE = 0x1F
KEY_SPACE = 0x20
KEY_BACKSPACE2 = 0x7F
KEY_CTRL_8 = 0x7F
MOD_ALT = 0x01
# attributes ----------------------
# -- mapped to tdl
DEFAULT = Ellipsis
BLACK = 0x000000
RED = 0xFF0000
GREEN = 0x00FF00
YELLOW = 0xFFFF00
BLUE = 0x0000FF
MAGENTA = 0xFF00FF
CYAN = 0x00FFFF
WHITE = 0xFFFFFF
# /--
BOLD = 0x10
UNDERLINE = 0x20
REVERSE = 0x40
# misc ----------------------------
HIDE_CURSOR = -1
INPUT_CURRENT = 0
INPUT_ESC = 1
INPUT_ALT = 2
OUTPUT_CURRENT = 0
OUTPUT_NORMAL = 1
OUTPUT_256 = 2
OUTPUT_216 = 3
OUTPUT_GRAYSCALE = 4
# -- mapped to tdl
EVENT_KEY = "KEYDOWN"
# /--
EVENT_RESIZE = 2
EVENT_MOUSE = 3
class Event:
"""Aggregate for Termbox Event structure."""
type = None
ch = None
key = None
mod = None
width = None
height = None
mousex = None
mousey = None
def gettuple(self):
return (self.type, self.ch, self.key, self.mod, self.width, self.height, self.mousex, self.mousey)
class Termbox:
def __init__(self, width=132, height=60) -> None:
global _instance
if _instance:
msg = "It is possible to create only one instance of Termbox"
raise TermboxException(msg)
try:
self.console = tdl.init(width, height)
except tdl.TDLException as e:
raise TermboxException(e)
self.e = Event() # cache for event data
_instance = self
def __del__(self) -> None:
self.close()
def __exit__(self, *args): # t, value, traceback):
self.close()
def __enter__(self):
return self
def close(self):
global _instance
# tb_shutdown()
_instance = None
# TBD, does nothing
def present(self):
"""Sync state of the internal cell buffer with the terminal."""
tdl.flush()
def change_cell(self, x, y, ch, fg, bg):
"""Change cell in position (x;y)."""
self.console.draw_char(x, y, ch, fg, bg)
def width(self):
"""Returns width of the terminal screen."""
return self.console.width
def height(self):
"""Return height of the terminal screen."""
return self.console.height
def clear(self):
"""Clear the internal cell buffer."""
self.console.clear()
def set_cursor(self, x, y):
"""Set cursor position to (x;y).
Set both arguments to HIDE_CURSOR or use 'hide_cursor' function to
hide it.
"""
tb_set_cursor(x, y)
def hide_cursor(self):
"""Hide cursor."""
tb_set_cursor(-1, -1)
def select_input_mode(self, mode):
"""Select preferred input mode: INPUT_ESC or INPUT_ALT.
INPUT_CURRENT returns the selected mode without changing anything.
"""
return int(tb_select_input_mode(mode))
def select_output_mode(self, mode):
"""Select preferred output mode: one of OUTPUT_* constants.
OUTPUT_CURRENT returns the selected mode without changing anything.
"""
return int(tb_select_output_mode(mode))
def peek_event(self, timeout=0):
"""Wait for an event up to 'timeout' milliseconds and return it.
Returns None if there was no event and timeout is expired.
Returns a tuple otherwise: (type, unicode character, key, mod,
width, height, mousex, mousey).
"""
"""
cdef tb_event e
with self._poll_lock:
with nogil:
result = tb_peek_event(&e, timeout)
assert(result >= 0)
if result == 0:
return None
if e.ch:
uch = unichr(e.ch)
else:
uch = None
"""
pass # return (e.type, uch, e.key, e.mod, e.w, e.h, e.x, e.y)
def poll_event(self):
"""Wait for an event and return it.
Returns a tuple: (type, unicode character, key, mod, width, height,
mousex, mousey).
"""
"""
cdef tb_event e
with self._poll_lock:
with nogil:
result = tb_poll_event(&e)
assert(result >= 0)
if e.ch:
uch = unichr(e.ch)
else:
uch = None
"""
for e in tdl.event.get():
# [ ] not all events are passed thru
self.e.type = e.type
if e.type == "KEYDOWN":
self.e.key = e.key
return self.e.gettuple()
return None
# return (e.type, uch, e.key, e.mod, e.w, e.h, e.x, e.y)