listpick 0.1.14.7__py3-none-any.whl → 0.1.14.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of listpick might be problematic. Click here for more details.
- listpick/listpick_app.py +27 -47
- listpick/ui/input_field.py +101 -105
- listpick/ui/keys.py +4 -2
- listpick/utils/keycodes.py +88 -0
- listpick/utils/user_input.py +104 -0
- {listpick-0.1.14.7.dist-info → listpick-0.1.14.9.dist-info}/METADATA +1 -1
- {listpick-0.1.14.7.dist-info → listpick-0.1.14.9.dist-info}/RECORD +11 -10
- listpick/ui/keycodes.py +0 -70
- {listpick-0.1.14.7.dist-info → listpick-0.1.14.9.dist-info}/WHEEL +0 -0
- {listpick-0.1.14.7.dist-info → listpick-0.1.14.9.dist-info}/entry_points.txt +0 -0
- {listpick-0.1.14.7.dist-info → listpick-0.1.14.9.dist-info}/licenses/LICENSE.txt +0 -0
- {listpick-0.1.14.7.dist-info → listpick-0.1.14.9.dist-info}/top_level.txt +0 -0
listpick/listpick_app.py
CHANGED
|
@@ -40,6 +40,7 @@ from listpick.utils.dump import dump_state, load_state, dump_data
|
|
|
40
40
|
from listpick.ui.build_help import build_help_rows
|
|
41
41
|
from listpick.ui.footer import StandardFooter, CompactFooter, NoFooter
|
|
42
42
|
from listpick.utils.picker_log import setup_logger
|
|
43
|
+
from listpick.utils.user_input import get_char, open_tty
|
|
43
44
|
|
|
44
45
|
|
|
45
46
|
try:
|
|
@@ -187,6 +188,8 @@ class Picker:
|
|
|
187
188
|
sheet_index = 0,
|
|
188
189
|
sheet_states = [{}],
|
|
189
190
|
|
|
191
|
+
redraw_screen_accessory: Callable = lambda : None,
|
|
192
|
+
|
|
190
193
|
):
|
|
191
194
|
self.stdscr = stdscr
|
|
192
195
|
self.items = items
|
|
@@ -335,6 +338,7 @@ class Picker:
|
|
|
335
338
|
self.sheet_states = sheet_states
|
|
336
339
|
self.sheets = sheets
|
|
337
340
|
|
|
341
|
+
self.redraw_screen_accessory = redraw_screen_accessory
|
|
338
342
|
self.initialise_picker_state(reset_colours=self.reset_colours)
|
|
339
343
|
|
|
340
344
|
# Note: We have to set the footer after initialising the picker state so that the footer can use the get_function_data method
|
|
@@ -747,6 +751,8 @@ class Picker:
|
|
|
747
751
|
|
|
748
752
|
def draw_screen_(self, indexed_items: list[Tuple[int, list[str]]], highlights: list[dict] = [{}], clear: bool = True) -> None:
|
|
749
753
|
""" Draw Picker screen. """
|
|
754
|
+
|
|
755
|
+
self.redraw_screen_accessory()
|
|
750
756
|
self.logger.debug("Draw screen.")
|
|
751
757
|
|
|
752
758
|
if clear:
|
|
@@ -876,10 +882,10 @@ class Picker:
|
|
|
876
882
|
else:
|
|
877
883
|
cell_value = self.indexed_items[row][1][col] + self.separator
|
|
878
884
|
# cell_value = cell_value[:min(cell_width, cell_max_width)-len(self.separator)]
|
|
879
|
-
cell_value = truncate_to_display_width(cell_value, min(cell_width, cell_max_width)-len(self.separator), self.unicode_char_width)
|
|
885
|
+
cell_value = truncate_to_display_width(cell_value, min(cell_width, cell_max_width)-len(self.separator), self.centre_in_cols, self.unicode_char_width)
|
|
880
886
|
cell_value = cell_value + self.separator
|
|
881
887
|
# cell_value = cell_value
|
|
882
|
-
cell_value = truncate_to_display_width(cell_value, min(cell_width, cell_max_width), self.unicode_char_width)
|
|
888
|
+
cell_value = truncate_to_display_width(cell_value, min(cell_width, cell_max_width), self.centre_in_cols, self.unicode_char_width)
|
|
883
889
|
# row_str = truncate_to_display_width(row_str_left_adj, min(w-self.startx, visible_columns_total_width))
|
|
884
890
|
self.stdscr.addstr(y, cell_pos, cell_value, curses.color_pair(self.colours_start+colour_pair_number) | curses.A_BOLD)
|
|
885
891
|
# Part of the cell is on screen
|
|
@@ -1121,6 +1127,7 @@ class Picker:
|
|
|
1121
1127
|
"hidden_columns": [],
|
|
1122
1128
|
"title": title,
|
|
1123
1129
|
"reset_colours": False,
|
|
1130
|
+
"cell_cursor": False,
|
|
1124
1131
|
}
|
|
1125
1132
|
|
|
1126
1133
|
OptionPicker = Picker(submenu_win, **infobox_data)
|
|
@@ -1235,6 +1242,7 @@ class Picker:
|
|
|
1235
1242
|
"sheets": self.sheets,
|
|
1236
1243
|
"sheet_name": self.sheet_name,
|
|
1237
1244
|
"sheet_states": self.sheet_states,
|
|
1245
|
+
"redraw_screen_accessory": self.redraw_screen_accessory,
|
|
1238
1246
|
}
|
|
1239
1247
|
return function_data
|
|
1240
1248
|
|
|
@@ -1269,6 +1277,7 @@ class Picker:
|
|
|
1269
1277
|
"centre_in_terminal_vertical",
|
|
1270
1278
|
"centre_in_cols",
|
|
1271
1279
|
"centre_in_terminal",
|
|
1280
|
+
"redraw_screen_accessory",
|
|
1272
1281
|
]
|
|
1273
1282
|
|
|
1274
1283
|
for var in variables:
|
|
@@ -1361,6 +1370,7 @@ class Picker:
|
|
|
1361
1370
|
"cancel_is_back": True,
|
|
1362
1371
|
"number_columns": False,
|
|
1363
1372
|
"reset_colours": False,
|
|
1373
|
+
"cell_cursor": False,
|
|
1364
1374
|
}
|
|
1365
1375
|
while True:
|
|
1366
1376
|
h, w = stdscr.getmaxyx()
|
|
@@ -1407,6 +1417,11 @@ class Picker:
|
|
|
1407
1417
|
|
|
1408
1418
|
submenu_win = curses.newwin(notification_height, notification_width, 3, w - (notification_width+4))
|
|
1409
1419
|
# submenu_win = self.stdscr.subwin(notification_height, notification_width, 3, w - (notification_width+4))
|
|
1420
|
+
def update_after_resize():
|
|
1421
|
+
h, w = self.stdscr.getmaxyx()
|
|
1422
|
+
submenu_win.mvwin(3, w - (notification_width+4))
|
|
1423
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
1424
|
+
|
|
1410
1425
|
notification_data = {
|
|
1411
1426
|
"items": submenu_items,
|
|
1412
1427
|
"title": title,
|
|
@@ -1427,9 +1442,15 @@ class Picker:
|
|
|
1427
1442
|
"loaded_file_states": [],
|
|
1428
1443
|
"loaded_file": "",
|
|
1429
1444
|
"loaded_file_index": 0,
|
|
1445
|
+
"cell_cursor": False,
|
|
1446
|
+
# "redraw_screen_accessory": lambda : self.draw_screen(self.indexed_items, self.highlights),
|
|
1447
|
+
"redraw_screen_accessory": update_after_resize,
|
|
1448
|
+
"get_new_data": False,
|
|
1449
|
+
# "key_remappings": notification_remap_keys,
|
|
1430
1450
|
}
|
|
1431
1451
|
OptionPicker = Picker(submenu_win, **notification_data)
|
|
1432
1452
|
s, o, f = OptionPicker.run()
|
|
1453
|
+
os.system(f"notify-send resizing")
|
|
1433
1454
|
|
|
1434
1455
|
if o != "refresh": break
|
|
1435
1456
|
submenu_win.clear()
|
|
@@ -1438,6 +1459,7 @@ class Picker:
|
|
|
1438
1459
|
stdscr.clear()
|
|
1439
1460
|
stdscr.refresh()
|
|
1440
1461
|
self.draw_screen(self.indexed_items, self.highlights)
|
|
1462
|
+
|
|
1441
1463
|
# set_colours(colours=get_colours(0))
|
|
1442
1464
|
|
|
1443
1465
|
def toggle_column_visibility(self, col_index:int) -> None:
|
|
@@ -2306,6 +2328,7 @@ class Picker:
|
|
|
2306
2328
|
"centre_in_terminal_vertical": True,
|
|
2307
2329
|
"hidden_columns": [],
|
|
2308
2330
|
"reset_colours": False,
|
|
2331
|
+
"cell_cursor": False,
|
|
2309
2332
|
|
|
2310
2333
|
}
|
|
2311
2334
|
OptionPicker = Picker(self.stdscr, **help_data)
|
|
@@ -2416,6 +2439,7 @@ class Picker:
|
|
|
2416
2439
|
"centre_in_terminal_vertical": True,
|
|
2417
2440
|
"hidden_columns": [],
|
|
2418
2441
|
"reset_colours": False,
|
|
2442
|
+
"cell_cursor": False,
|
|
2419
2443
|
|
|
2420
2444
|
}
|
|
2421
2445
|
OptionPicker = Picker(self.stdscr, **info_data)
|
|
@@ -3575,50 +3599,6 @@ def unrestrict_curses(stdscr: curses.window) -> None:
|
|
|
3575
3599
|
curses.curs_set(False)
|
|
3576
3600
|
|
|
3577
3601
|
|
|
3578
|
-
def open_tty():
|
|
3579
|
-
""" Return a file descriptor for the tty that we are opening"""
|
|
3580
|
-
tty_fd = os.open('/dev/tty', os.O_RDONLY)
|
|
3581
|
-
tty.setraw(tty_fd)
|
|
3582
|
-
return tty_fd
|
|
3583
|
-
|
|
3584
|
-
def get_char(tty_fd, timeout: float = 0.2, secondary: bool = False) -> int:
|
|
3585
|
-
""" Get character from a tty_fd with a timeout. """
|
|
3586
|
-
rlist, _, _ = select.select([tty_fd], [], [], timeout)
|
|
3587
|
-
if rlist:
|
|
3588
|
-
# key = ord(tty_fd.read(1))
|
|
3589
|
-
key = ord(os.read(tty_fd, 1))
|
|
3590
|
-
if not secondary:
|
|
3591
|
-
if key == 27:
|
|
3592
|
-
key2 = get_char(tty_fd, timeout=0.01, secondary=True)
|
|
3593
|
-
key3 = get_char(tty_fd, timeout=0.01, secondary=True)
|
|
3594
|
-
key4 = get_char(tty_fd, timeout=0.01, secondary=True)
|
|
3595
|
-
key5 = get_char(tty_fd, timeout=0.01, secondary=True)
|
|
3596
|
-
if key2 == ord('O') and key3 == ord('B'):
|
|
3597
|
-
key = curses.KEY_DOWN
|
|
3598
|
-
elif key2 == ord('O') and key3 == ord('A'):
|
|
3599
|
-
key = curses.KEY_UP
|
|
3600
|
-
elif key2 == ord('O') and key3 == ord('D'):
|
|
3601
|
-
key = curses.KEY_LEFT
|
|
3602
|
-
elif key2 == ord('O') and key3 == ord('C'):
|
|
3603
|
-
key = curses.KEY_RIGHT
|
|
3604
|
-
elif key2 == ord('[') and key3 == ord('Z'):
|
|
3605
|
-
key = 353
|
|
3606
|
-
elif key2 == ord('O') and key3 == ord('F'):
|
|
3607
|
-
key = curses.KEY_END
|
|
3608
|
-
elif key2 == ord('O') and key3 == ord('H'):
|
|
3609
|
-
key = curses.KEY_HOME
|
|
3610
|
-
elif key2 == ord('[') and key3 == ord('3') and key4 == ord('~'):
|
|
3611
|
-
key = curses.KEY_DC
|
|
3612
|
-
elif key2 == ord('[') and key3 == ord('3') and key4 == ord('~'):
|
|
3613
|
-
key = curses.KEY_DC
|
|
3614
|
-
elif key2 == ord('O') and key3 == ord('P'):
|
|
3615
|
-
key = curses.KEY_F1
|
|
3616
|
-
elif key2 == ord('[') and key3 == ord('1') and key4 == ord('5') and key5 == ord('~'):
|
|
3617
|
-
key = curses.KEY_F5
|
|
3618
|
-
|
|
3619
|
-
else:
|
|
3620
|
-
key = -1
|
|
3621
|
-
return key
|
|
3622
3602
|
|
|
3623
3603
|
def main() -> None:
|
|
3624
3604
|
""" Main function when listpick is executed. Deals with command line arguments and starts a Picker. """
|
|
@@ -3693,7 +3673,7 @@ def main() -> None:
|
|
|
3693
3673
|
app.load_input_history("~/.config/listpick/cmdhist.json")
|
|
3694
3674
|
app.run()
|
|
3695
3675
|
|
|
3696
|
-
|
|
3676
|
+
app.save_input_history("~/.config/listpick/cmdhist.json")
|
|
3697
3677
|
except Exception as e:
|
|
3698
3678
|
print(e)
|
|
3699
3679
|
|
listpick/ui/input_field.py
CHANGED
|
@@ -18,22 +18,24 @@ import logging
|
|
|
18
18
|
logger = logging.getLogger('picker_log')
|
|
19
19
|
import select
|
|
20
20
|
import tty
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
21
|
+
from listpick.utils.user_input import get_char, open_tty
|
|
22
|
+
from listpick.utils import keycodes
|
|
23
|
+
|
|
24
|
+
# def open_tty():
|
|
25
|
+
# """ Return a file descriptor for the tty that we are opening"""
|
|
26
|
+
# tty_fd = os.open('/dev/tty', os.O_RDONLY)
|
|
27
|
+
# tty.setraw(tty_fd)
|
|
28
|
+
# return tty_fd
|
|
29
|
+
#
|
|
30
|
+
# def get_char(tty_fd, timeout: float = 0.2) -> int:
|
|
31
|
+
# """ Get character from a tty_fd with a timeout. """
|
|
32
|
+
# rlist, _, _ = select.select([tty_fd], [], [], timeout)
|
|
33
|
+
# if rlist:
|
|
34
|
+
# # key = ord(tty_fd.read(1))
|
|
35
|
+
# key = ord(os.read(tty_fd, 1))
|
|
36
|
+
# else:
|
|
37
|
+
# key = -1
|
|
38
|
+
# return key
|
|
37
39
|
|
|
38
40
|
def input_field(
|
|
39
41
|
stdscr: curses.window,
|
|
@@ -230,100 +232,94 @@ def input_field(
|
|
|
230
232
|
key = get_char(tty_fd, timeout=0.5)
|
|
231
233
|
# key = stdscr.getch()
|
|
232
234
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
for word_separator_char in word_separator_chars:
|
|
247
|
-
tmp_index = search_txt[::-1].find(word_separator_char)
|
|
248
|
-
if tmp_index > -1:
|
|
249
|
-
if index == -1:
|
|
250
|
-
index = tmp_index
|
|
251
|
-
else:
|
|
252
|
-
index = min(index, tmp_index)
|
|
253
|
-
|
|
254
|
-
if index == -1:
|
|
255
|
-
if cursor == 0:
|
|
256
|
-
kill_ring.append(usrtxt)
|
|
257
|
-
usrtxt = ""
|
|
258
|
-
else:
|
|
259
|
-
kill_ring.append(usrtxt[:-(cursor+1)])
|
|
260
|
-
usrtxt = usrtxt[-(cursor+1):]
|
|
261
|
-
cursor = len(usrtxt)
|
|
262
|
-
else:
|
|
263
|
-
if index == 0:
|
|
264
|
-
kill_ring.append(search_txt[-1:])
|
|
265
|
-
usrtxt = search_txt[:-1] + usrtxt[len(search_txt):]
|
|
235
|
+
|
|
236
|
+
if key in [27, 7]: # ESC/ALT key or Ctrl+g
|
|
237
|
+
return "", False
|
|
238
|
+
|
|
239
|
+
elif key == keycodes.META_BS:
|
|
240
|
+
# Delete to backslash or space (word_separator_chars)
|
|
241
|
+
search_txt = usrtxt[:-cursor] if cursor > 0 else usrtxt
|
|
242
|
+
index = -1
|
|
243
|
+
for word_separator_char in word_separator_chars:
|
|
244
|
+
tmp_index = search_txt[::-1].find(word_separator_char)
|
|
245
|
+
if tmp_index > -1:
|
|
246
|
+
if index == -1:
|
|
247
|
+
index = tmp_index
|
|
266
248
|
else:
|
|
267
|
-
|
|
268
|
-
usrtxt = search_txt[:-index] + usrtxt[len(search_txt):]
|
|
249
|
+
index = min(index, tmp_index)
|
|
269
250
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
# Forward word
|
|
275
|
-
search_txt = usrtxt[-cursor:]
|
|
276
|
-
index = -1
|
|
277
|
-
for word_separator_char in word_separator_chars:
|
|
278
|
-
tmp_index = search_txt.find(word_separator_char)
|
|
279
|
-
|
|
280
|
-
if tmp_index > -1:
|
|
281
|
-
if index == -1:
|
|
282
|
-
index = tmp_index
|
|
283
|
-
else:
|
|
284
|
-
index = min(index, tmp_index)
|
|
285
|
-
|
|
286
|
-
if index == -1:
|
|
287
|
-
cursor = 0
|
|
251
|
+
if index == -1:
|
|
252
|
+
if cursor == 0:
|
|
253
|
+
kill_ring.append(usrtxt)
|
|
254
|
+
usrtxt = ""
|
|
288
255
|
else:
|
|
289
|
-
cursor
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
index = -1
|
|
297
|
-
for word_separator_char in word_separator_chars:
|
|
298
|
-
tmp_index = search_txt[::-1].find(word_separator_char)
|
|
299
|
-
|
|
300
|
-
if tmp_index == 0:
|
|
301
|
-
tmp_index = search_txt[:-1][::-1].find(word_separator_char)
|
|
302
|
-
|
|
303
|
-
if tmp_index > -1:
|
|
304
|
-
if index == -1:
|
|
305
|
-
index = tmp_index
|
|
306
|
-
else:
|
|
307
|
-
index = min(index, tmp_index)
|
|
308
|
-
|
|
309
|
-
if index == -1:
|
|
310
|
-
cursor = len(usrtxt)
|
|
256
|
+
kill_ring.append(usrtxt[:-(cursor+1)])
|
|
257
|
+
usrtxt = usrtxt[-(cursor+1):]
|
|
258
|
+
cursor = len(usrtxt)
|
|
259
|
+
else:
|
|
260
|
+
if index == 0:
|
|
261
|
+
kill_ring.append(search_txt[-1:])
|
|
262
|
+
usrtxt = search_txt[:-1] + usrtxt[len(search_txt):]
|
|
311
263
|
else:
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
264
|
+
kill_ring.append(search_txt[-index:])
|
|
265
|
+
usrtxt = search_txt[:-index] + usrtxt[len(search_txt):]
|
|
266
|
+
|
|
267
|
+
potential_path = usrtxt
|
|
268
|
+
kill_ring_active = False
|
|
269
|
+
|
|
270
|
+
elif key == keycodes.META_f:
|
|
271
|
+
# Forward word
|
|
272
|
+
search_txt = usrtxt[-cursor:]
|
|
273
|
+
index = -1
|
|
274
|
+
for word_separator_char in word_separator_chars:
|
|
275
|
+
tmp_index = search_txt.find(word_separator_char)
|
|
276
|
+
|
|
277
|
+
if tmp_index > -1:
|
|
278
|
+
if index == -1:
|
|
279
|
+
index = tmp_index
|
|
280
|
+
else:
|
|
281
|
+
index = min(index, tmp_index)
|
|
282
|
+
|
|
283
|
+
if index == -1:
|
|
284
|
+
cursor = 0
|
|
285
|
+
else:
|
|
286
|
+
cursor -= index + 1
|
|
287
|
+
cursor = max(cursor, 0)
|
|
288
|
+
kill_ring_active = False
|
|
289
|
+
|
|
290
|
+
elif key == keycodes.META_b:
|
|
291
|
+
# Backwards word
|
|
292
|
+
search_txt = usrtxt[:-cursor] if cursor > 0 else usrtxt
|
|
293
|
+
index = -1
|
|
294
|
+
for word_separator_char in word_separator_chars:
|
|
295
|
+
tmp_index = search_txt[::-1].find(word_separator_char)
|
|
296
|
+
|
|
297
|
+
if tmp_index == 0:
|
|
298
|
+
tmp_index = search_txt[:-1][::-1].find(word_separator_char)
|
|
299
|
+
|
|
300
|
+
if tmp_index > -1:
|
|
301
|
+
if index == -1:
|
|
302
|
+
index = tmp_index
|
|
322
303
|
else:
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
304
|
+
index = min(index, tmp_index)
|
|
305
|
+
|
|
306
|
+
if index == -1:
|
|
307
|
+
cursor = len(usrtxt)
|
|
308
|
+
else:
|
|
309
|
+
cursor += index + 1
|
|
310
|
+
kill_ring_active = False
|
|
311
|
+
|
|
312
|
+
elif key == keycodes.META_y:
|
|
313
|
+
# Kill ring
|
|
314
|
+
prev_kill_ring_index = kill_ring_index
|
|
315
|
+
kill_ring_index = (kill_ring_index + 1)%len(kill_ring)
|
|
316
|
+
if kill_ring_active and len(kill_ring):
|
|
317
|
+
if cursor == 0:
|
|
318
|
+
usrtxt = usrtxt[:-len(kill_ring[prev_kill_ring_index])]
|
|
319
|
+
usrtxt += kill_ring[kill_ring_index]
|
|
320
|
+
else:
|
|
321
|
+
usrtxt = usrtxt[-cursor:-(cursor+len(kill_ring[prev_kill_ring_index]))]
|
|
322
|
+
usrtxt = usrtxt[:-cursor] + kill_ring[kill_ring_index] + usrtxt[-cursor:]
|
|
327
323
|
|
|
328
324
|
elif key == 3: # ctrl+c
|
|
329
325
|
# Immediate exit
|
listpick/ui/keys.py
CHANGED
|
@@ -9,6 +9,7 @@ License: MIT
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
import curses
|
|
12
|
+
from listpick.utils import keycodes
|
|
12
13
|
|
|
13
14
|
picker_keys = {
|
|
14
15
|
"refresh": [curses.KEY_F5],
|
|
@@ -25,8 +26,8 @@ picker_keys = {
|
|
|
25
26
|
"page_down": [curses.KEY_NPAGE, 6], # Ctrl+f
|
|
26
27
|
"cursor_bottom": [ord('G'), curses.KEY_END],
|
|
27
28
|
"cursor_top": [ord('g'), curses.KEY_HOME],
|
|
28
|
-
"five_up": [ord('K')],
|
|
29
|
-
"five_down": [ord('J')],
|
|
29
|
+
"five_up": [ord('K'), keycodes.META_k],
|
|
30
|
+
"five_down": [ord('J'), keycodes.META_j],
|
|
30
31
|
"toggle_select": [ord(' ')],
|
|
31
32
|
"select_all": [ord('m'), 1], # Ctrl-a
|
|
32
33
|
"select_none": [ord('M'), 18], # Ctrl-r
|
|
@@ -135,6 +136,7 @@ notification_keys = {
|
|
|
135
136
|
"five_up": [ord('K')],
|
|
136
137
|
"five_down": [ord('J')],
|
|
137
138
|
"redraw_screen": [12], # Ctrl-l
|
|
139
|
+
"refresh": [curses.KEY_F5, curses.KEY_RESIZE],
|
|
138
140
|
}
|
|
139
141
|
|
|
140
142
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Set a base value to ensure that we have no collisions with any unicode characters
|
|
2
|
+
BASE_VALUE = 2**32
|
|
3
|
+
|
|
4
|
+
# Define constants for alt+a to alt+z
|
|
5
|
+
META_A = BASE_VALUE + 1000
|
|
6
|
+
META_B = BASE_VALUE + 1001
|
|
7
|
+
META_C = BASE_VALUE + 1002
|
|
8
|
+
META_D = BASE_VALUE + 1003
|
|
9
|
+
META_E = BASE_VALUE + 1004
|
|
10
|
+
META_F = BASE_VALUE + 1005
|
|
11
|
+
META_G = BASE_VALUE + 1006
|
|
12
|
+
META_H = BASE_VALUE + 1007
|
|
13
|
+
META_I = BASE_VALUE + 1008
|
|
14
|
+
META_J = BASE_VALUE + 1009
|
|
15
|
+
META_K = BASE_VALUE + 1010
|
|
16
|
+
META_L = BASE_VALUE + 1011
|
|
17
|
+
META_M = BASE_VALUE + 1012
|
|
18
|
+
META_N = BASE_VALUE + 1013
|
|
19
|
+
META_O = BASE_VALUE + 1014
|
|
20
|
+
META_P = BASE_VALUE + 1015
|
|
21
|
+
META_Q = BASE_VALUE + 1016
|
|
22
|
+
META_R = BASE_VALUE + 1017
|
|
23
|
+
META_S = BASE_VALUE + 1018
|
|
24
|
+
META_T = BASE_VALUE + 1019
|
|
25
|
+
META_U = BASE_VALUE + 1020
|
|
26
|
+
META_V = BASE_VALUE + 1021
|
|
27
|
+
META_W = BASE_VALUE + 1022
|
|
28
|
+
META_X = BASE_VALUE + 1023
|
|
29
|
+
META_Y = BASE_VALUE + 1024
|
|
30
|
+
META_Z = BASE_VALUE + 1025
|
|
31
|
+
|
|
32
|
+
# Define constants for alt+A to alt+Z (using uppercase)
|
|
33
|
+
META_a = BASE_VALUE + 1050
|
|
34
|
+
META_b = BASE_VALUE + 1051
|
|
35
|
+
META_c = BASE_VALUE + 1052
|
|
36
|
+
META_d = BASE_VALUE + 1053
|
|
37
|
+
META_e = BASE_VALUE + 1054
|
|
38
|
+
META_f = BASE_VALUE + 1055
|
|
39
|
+
META_g = BASE_VALUE + 1056
|
|
40
|
+
META_h = BASE_VALUE + 1057
|
|
41
|
+
META_i = BASE_VALUE + 1058
|
|
42
|
+
META_j = BASE_VALUE + 1059
|
|
43
|
+
META_k = BASE_VALUE + 1060
|
|
44
|
+
META_l = BASE_VALUE + 1061
|
|
45
|
+
META_m = BASE_VALUE + 1062
|
|
46
|
+
META_n = BASE_VALUE + 1063
|
|
47
|
+
META_o = BASE_VALUE + 1064
|
|
48
|
+
META_p = BASE_VALUE + 1065
|
|
49
|
+
META_q = BASE_VALUE + 1066
|
|
50
|
+
META_r = BASE_VALUE + 1067
|
|
51
|
+
META_s = BASE_VALUE + 1068
|
|
52
|
+
META_t = BASE_VALUE + 1069
|
|
53
|
+
META_u = BASE_VALUE + 1070
|
|
54
|
+
META_v = BASE_VALUE + 1071
|
|
55
|
+
META_w = BASE_VALUE + 1072
|
|
56
|
+
META_x = BASE_VALUE + 1073
|
|
57
|
+
META_y = BASE_VALUE + 1074
|
|
58
|
+
META_z = BASE_VALUE + 1075
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
META_0 = BASE_VALUE + 1090
|
|
62
|
+
META_1 = BASE_VALUE + 1091
|
|
63
|
+
META_2 = BASE_VALUE + 1092
|
|
64
|
+
META_3 = BASE_VALUE + 1093
|
|
65
|
+
META_4 = BASE_VALUE + 1094
|
|
66
|
+
META_5 = BASE_VALUE + 1095
|
|
67
|
+
META_6 = BASE_VALUE + 1096
|
|
68
|
+
META_7 = BASE_VALUE + 1097
|
|
69
|
+
META_8 = BASE_VALUE + 1098
|
|
70
|
+
META_9 = BASE_VALUE + 1099
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
META_BS = BASE_VALUE + 1100
|
|
74
|
+
|
|
75
|
+
# Dictionary to map character to its constant value
|
|
76
|
+
META_KEY_MAP = {
|
|
77
|
+
'a': META_a, 'b': META_b, 'c': META_c, 'd': META_d, 'e': META_e,
|
|
78
|
+
'f': META_f, 'g': META_g, 'h': META_h, 'i': META_i, 'j': META_j,
|
|
79
|
+
'k': META_k, 'l': META_l, 'm': META_m, 'n': META_n, 'o': META_o,
|
|
80
|
+
'p': META_p, 'q': META_q, 'r': META_r, 's': META_s, 't': META_t,
|
|
81
|
+
'u': META_u, 'v': META_v, 'w': META_w, 'x': META_x, 'y': META_y,
|
|
82
|
+
'z': META_z, 'A': META_A, 'B': META_B, 'C': META_C, 'D': META_D,
|
|
83
|
+
'E': META_E, 'F': META_F, 'G': META_G, 'H': META_H, 'I': META_I,
|
|
84
|
+
'J': META_J, 'K': META_K, 'L': META_L, 'M': META_M, 'N': META_N,
|
|
85
|
+
'O': META_O, 'P': META_P, 'Q': META_Q, 'R': META_R, 'S': META_S,
|
|
86
|
+
'T': META_T, 'U': META_U, 'V': META_V, 'W': META_W, 'X': META_X,
|
|
87
|
+
'Y': META_Y, 'Z': META_Z
|
|
88
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from listpick.utils import keycodes
|
|
2
|
+
import os, tty, select, curses
|
|
3
|
+
|
|
4
|
+
def open_tty():
|
|
5
|
+
""" Return a file descriptor for the tty that we are opening"""
|
|
6
|
+
tty_fd = os.open('/dev/tty', os.O_RDONLY)
|
|
7
|
+
tty.setraw(tty_fd)
|
|
8
|
+
return tty_fd
|
|
9
|
+
|
|
10
|
+
def get_char(tty_fd, timeout: float = 0.2, secondary: bool = False) -> int:
|
|
11
|
+
""" Get character from a tty_fd with a timeout. """
|
|
12
|
+
rlist, _, _ = select.select([tty_fd], [], [], timeout)
|
|
13
|
+
if rlist:
|
|
14
|
+
# key = ord(tty_fd.read(1))
|
|
15
|
+
key = ord(os.read(tty_fd, 1))
|
|
16
|
+
if not secondary:
|
|
17
|
+
if key == 27:
|
|
18
|
+
key2 = get_char(tty_fd, timeout=0.01, secondary=True)
|
|
19
|
+
key3 = get_char(tty_fd, timeout=0.01, secondary=True)
|
|
20
|
+
key4 = get_char(tty_fd, timeout=0.01, secondary=True)
|
|
21
|
+
key5 = get_char(tty_fd, timeout=0.01, secondary=True)
|
|
22
|
+
key6 = get_char(tty_fd, timeout=0.01, secondary=True)
|
|
23
|
+
|
|
24
|
+
keys = [key2, key3, key4, key5, key6]
|
|
25
|
+
|
|
26
|
+
key_str = "".join([chr(k) for k in keys if k != -1])
|
|
27
|
+
|
|
28
|
+
## Arrow Keys
|
|
29
|
+
if key2 == ord('O') and key3 == ord('B'):
|
|
30
|
+
key = curses.KEY_DOWN
|
|
31
|
+
elif key2 == ord('O') and key3 == ord('A'):
|
|
32
|
+
key = curses.KEY_UP
|
|
33
|
+
elif key2 == ord('O') and key3 == ord('D'):
|
|
34
|
+
key = curses.KEY_LEFT
|
|
35
|
+
elif key2 == ord('O') and key3 == ord('C'):
|
|
36
|
+
key = curses.KEY_RIGHT
|
|
37
|
+
|
|
38
|
+
## Shift+ Tab
|
|
39
|
+
elif key2 == ord('[') and key3 == ord('Z'):
|
|
40
|
+
key = 353
|
|
41
|
+
|
|
42
|
+
## Home, End, Pgup, Pgdn
|
|
43
|
+
elif key2 == ord('O') and key3 == ord('F'):
|
|
44
|
+
key = curses.KEY_END
|
|
45
|
+
elif key2 == ord('O') and key3 == ord('H'):
|
|
46
|
+
key = curses.KEY_HOME
|
|
47
|
+
elif key2 == ord('[') and key3 == ord('6') and key4 == ord("~"):
|
|
48
|
+
key = curses.KEY_NPAGE
|
|
49
|
+
elif key2 == ord('[') and key3 == ord('5') and key4 == ord("~"):
|
|
50
|
+
key = curses.KEY_PPAGE
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# Delete key
|
|
54
|
+
elif key_str == "[3~": ## Delete
|
|
55
|
+
key = curses.KEY_DC
|
|
56
|
+
elif key_str == "[3;2~": ## Shift+Delete
|
|
57
|
+
key = 383
|
|
58
|
+
|
|
59
|
+
## Function Keys
|
|
60
|
+
elif key2 == ord('O') and key3 == ord('P'):
|
|
61
|
+
key = curses.KEY_F1
|
|
62
|
+
elif key_str == "OQ":
|
|
63
|
+
key = curses.KEY_F2
|
|
64
|
+
elif key_str == "OR":
|
|
65
|
+
key = curses.KEY_F3
|
|
66
|
+
elif key_str == "OS":
|
|
67
|
+
key = curses.KEY_F4
|
|
68
|
+
elif key_str == "[15~":
|
|
69
|
+
key = curses.KEY_F5
|
|
70
|
+
elif key_str == "[17~":
|
|
71
|
+
key = curses.KEY_F6
|
|
72
|
+
elif key_str == "[17~":
|
|
73
|
+
key = curses.KEY_F7
|
|
74
|
+
elif key_str == "[19~":
|
|
75
|
+
key = curses.KEY_F8
|
|
76
|
+
elif key_str == "[20~":
|
|
77
|
+
key = curses.KEY_F9
|
|
78
|
+
elif key_str == "[21~":
|
|
79
|
+
key = curses.KEY_F10
|
|
80
|
+
elif key_str == "[23~":
|
|
81
|
+
key = curses.KEY_F11
|
|
82
|
+
elif key_str == "[24~":
|
|
83
|
+
key = curses.KEY_F12
|
|
84
|
+
|
|
85
|
+
## Alt+KEY
|
|
86
|
+
elif key2 >= ord('a') and key2 <= ord('z') and key3 == -1: ## Alt+[a-zA-Z]
|
|
87
|
+
key = keycodes.META_a + (key2 - ord('a'))
|
|
88
|
+
elif key2 >= ord('A') and key2 <= ord('Z') and key3 == -1: ## Alt+[a-zA-Z]
|
|
89
|
+
key = keycodes.META_A + (key2 - ord('A'))
|
|
90
|
+
elif key2 == ord('0') and key3 == -1: ## Alt+0
|
|
91
|
+
key = keycodes.META_0
|
|
92
|
+
elif key2 >= ord('1') and key2 <= ord('9') and key3 == -1: ## Alt+1-9
|
|
93
|
+
key = keycodes.META_1 + (key2 - ord('1'))
|
|
94
|
+
elif key2 == 127: ## Alt+BS
|
|
95
|
+
key = keycodes.META_BS
|
|
96
|
+
|
|
97
|
+
# If it is an unknown key with an escape sequence then return -1.
|
|
98
|
+
elif key2 != -1:
|
|
99
|
+
key = -1
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
else:
|
|
103
|
+
key = -1
|
|
104
|
+
return key
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
listpick/__init__.py,sha256=ExXc97-bibodH--wlwpQivl0zCNR5D1hvpvrf7OBofU,154
|
|
2
2
|
listpick/__main__.py,sha256=wkCjDdqw093W27yWwnlC3nG_sMRKaIad7hHHWy0RBgY,193
|
|
3
|
-
listpick/listpick_app.py,sha256=
|
|
3
|
+
listpick/listpick_app.py,sha256=9urXL8NUghj8tdbUCLxCa48nrgzeW4B41lv0_b_LRAw,187823
|
|
4
4
|
listpick/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
listpick/ui/build_help.py,sha256=8QtsRosIE2IMagRc_remzmwSWpCurFgLenLL7w1ly94,8949
|
|
6
6
|
listpick/ui/footer.py,sha256=ZM5OWCxOZqy5RG6tFTe1ipvu9PRu6Gh3JCA8KXBR_Wc,15004
|
|
7
7
|
listpick/ui/help_screen.py,sha256=zbfGIgb-IXtATpl4_Sx7nPbsnRXZ7eiMYlCKGS9EFmw,5608
|
|
8
|
-
listpick/ui/input_field.py,sha256=
|
|
9
|
-
listpick/ui/
|
|
10
|
-
listpick/ui/keys.py,sha256=C9wG_VPhaXq_c2bREBGKhd4Tb-AKqqOgub7y4W8xQmI,13182
|
|
8
|
+
listpick/ui/input_field.py,sha256=ylf3fiLXdAD4pueHWfzIrlwaRb9f5zm8f1UGkEPBxgM,30539
|
|
9
|
+
listpick/ui/keys.py,sha256=7ZhJfsSatpk-jwfXj_FvzgQsQdUoF7JkD5Mniu9XZ0o,13328
|
|
11
10
|
listpick/ui/pane_stuff.py,sha256=7GXa4UnV_7YmBv-baRi5moN51wYcuS4p0odl5C3m0Tc,169
|
|
12
11
|
listpick/ui/picker_colours.py,sha256=FLOzvkq83orrN2bL0Mw-6RugWOZyuwUjQCrUFMUnKGY,11563
|
|
13
12
|
listpick/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -16,6 +15,7 @@ listpick/utils/config.py,sha256=MEnAZg2Rhfl38XofEIN0uoVAOY7I0ftc79Evk3fOiVw,1654
|
|
|
16
15
|
listpick/utils/dump.py,sha256=60YVIMNtBoYvWhmzfTJOsNGcetOvcCB3_T7yv-bYTPQ,3838
|
|
17
16
|
listpick/utils/filtering.py,sha256=uS9sW0inmFvq0cIrwRC1BfuP8kjAD5IWWtls4jGB-70,1199
|
|
18
17
|
listpick/utils/generate_data.py,sha256=7sv6JRhk0-Gcj4kOlkzx4qPNBJZ-GFWg9vM77GktzpI,3073
|
|
18
|
+
listpick/utils/keycodes.py,sha256=ZGkw1-4szxPnP81wj80r92L6_neIOlBBjQltEieCwnk,2696
|
|
19
19
|
listpick/utils/options_selectors.py,sha256=Vbv4jRkUsSPs7g-EQAv9Q0nhYy6Z4sFsJqMjUIe1oeQ,2814
|
|
20
20
|
listpick/utils/paste_operations.py,sha256=7wDXLPlxUgA3CA99gwsm47juWGO2YQ9EJghW06yo9vI,1242
|
|
21
21
|
listpick/utils/picker_log.py,sha256=SW6GmjxpI7YrSf72fSr4O8Ux0fY_OzaSXUgTFdz6Xo4,805
|
|
@@ -23,10 +23,11 @@ listpick/utils/search_and_filter_utils.py,sha256=XxGfkyDVXO9OAKcftPat8IReMTFIuTH
|
|
|
23
23
|
listpick/utils/searching.py,sha256=Xk5UIqamNHL2L90z3ACB_Giqdpi9iRKoAJ6pKaqaD7Q,3093
|
|
24
24
|
listpick/utils/sorting.py,sha256=WZZiVlVA3Zkcpwji3U5SNFlQ14zVEk3cZJtQirBkecQ,5329
|
|
25
25
|
listpick/utils/table_to_list_of_lists.py,sha256=XBj7eGBDF15BRME-swnoXyOfZWxXCxrXp0pzsBfcJ5g,12224
|
|
26
|
+
listpick/utils/user_input.py,sha256=oyJZPAwA7UGAclPhdPL44tKnPIVNHWhX-tZEnCdBKC0,4318
|
|
26
27
|
listpick/utils/utils.py,sha256=McOl9uT3jh7l4TIWeSd8ZGjK_e7r0YZF0Gl20yI6fl0,13873
|
|
27
|
-
listpick-0.1.14.
|
|
28
|
-
listpick-0.1.14.
|
|
29
|
-
listpick-0.1.14.
|
|
30
|
-
listpick-0.1.14.
|
|
31
|
-
listpick-0.1.14.
|
|
32
|
-
listpick-0.1.14.
|
|
28
|
+
listpick-0.1.14.9.dist-info/licenses/LICENSE.txt,sha256=2mP-MRHJptADDNE9VInMNg1tE-C6Qv93Z4CCQKrpg9w,1061
|
|
29
|
+
listpick-0.1.14.9.dist-info/METADATA,sha256=kgR_E4Y4IFLqmrx8nDzgLOvHqW41BPWYuAv_BX8j0bU,8090
|
|
30
|
+
listpick-0.1.14.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
31
|
+
listpick-0.1.14.9.dist-info/entry_points.txt,sha256=-QCf_BKIkUz35Y9nkYpjZWs2Qg0KfRna2PAs5DnF6BE,43
|
|
32
|
+
listpick-0.1.14.9.dist-info/top_level.txt,sha256=5mtsGEz86rz3qQDe0D463gGjAfSp6A3EWg4J4AGYr-Q,9
|
|
33
|
+
listpick-0.1.14.9.dist-info/RECORD,,
|
listpick/ui/keycodes.py
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
# Define constants for alt+a to alt+z
|
|
2
|
-
META_A = 1000
|
|
3
|
-
META_B = 1001
|
|
4
|
-
META_C = 1002
|
|
5
|
-
META_D = 1003
|
|
6
|
-
META_E = 1004
|
|
7
|
-
META_F = 1005
|
|
8
|
-
META_G = 1006
|
|
9
|
-
META_H = 1007
|
|
10
|
-
META_I = 1008
|
|
11
|
-
META_J = 1009
|
|
12
|
-
META_K = 1010
|
|
13
|
-
META_L = 1011
|
|
14
|
-
META_M = 1012
|
|
15
|
-
META_N = 1013
|
|
16
|
-
META_O = 1014
|
|
17
|
-
META_P = 1015
|
|
18
|
-
META_Q = 1016
|
|
19
|
-
META_R = 1017
|
|
20
|
-
META_S = 1018
|
|
21
|
-
META_T = 1019
|
|
22
|
-
META_U = 1020
|
|
23
|
-
META_V = 1021
|
|
24
|
-
META_W = 1022
|
|
25
|
-
META_X = 1023
|
|
26
|
-
META_Y = 1024
|
|
27
|
-
META_Z = 1025
|
|
28
|
-
|
|
29
|
-
# Define constants for alt+A to alt+Z (using uppercase)
|
|
30
|
-
META_a = 1050
|
|
31
|
-
META_b = 1051
|
|
32
|
-
META_c = 1052
|
|
33
|
-
META_d = 1053
|
|
34
|
-
META_e = 1054
|
|
35
|
-
META_f = 1055
|
|
36
|
-
META_g = 1056
|
|
37
|
-
META_h = 1057
|
|
38
|
-
META_i = 1058
|
|
39
|
-
META_j = 1059
|
|
40
|
-
META_k = 1060
|
|
41
|
-
META_l = 1061
|
|
42
|
-
META_m = 1062
|
|
43
|
-
META_n = 1063
|
|
44
|
-
META_o = 1064
|
|
45
|
-
META_p = 1065
|
|
46
|
-
META_q = 1066
|
|
47
|
-
META_r = 1067
|
|
48
|
-
META_s = 1068
|
|
49
|
-
META_t = 1069
|
|
50
|
-
META_u = 1070
|
|
51
|
-
META_v = 1071
|
|
52
|
-
META_w = 1072
|
|
53
|
-
META_x = 1073
|
|
54
|
-
META_y = 1074
|
|
55
|
-
META_z = 1075
|
|
56
|
-
|
|
57
|
-
# Dictionary to map character to its constant value
|
|
58
|
-
META_KEY_MAP = {
|
|
59
|
-
'a': META_a, 'b': META_b, 'c': META_c, 'd': META_d, 'e': META_e,
|
|
60
|
-
'f': META_f, 'g': META_g, 'h': META_h, 'i': META_i, 'j': META_j,
|
|
61
|
-
'k': META_k, 'l': META_l, 'm': META_m, 'n': META_n, 'o': META_o,
|
|
62
|
-
'p': META_p, 'q': META_q, 'r': META_r, 's': META_s, 't': META_t,
|
|
63
|
-
'u': META_u, 'v': META_v, 'w': META_w, 'x': META_x, 'y': META_y,
|
|
64
|
-
'z': META_z, 'A': META_A, 'B': META_B, 'C': META_C, 'D': META_D,
|
|
65
|
-
'E': META_E, 'F': META_F, 'G': META_G, 'H': META_H, 'I': META_I,
|
|
66
|
-
'J': META_J, 'K': META_K, 'L': META_L, 'M': META_M, 'N': META_N,
|
|
67
|
-
'O': META_O, 'P': META_P, 'Q': META_Q, 'R': META_R, 'S': META_S,
|
|
68
|
-
'T': META_T, 'U': META_U, 'V': META_V, 'W': META_W, 'X': META_X,
|
|
69
|
-
'Y': META_Y, 'Z': META_Z
|
|
70
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|