listpick 0.1.13.55__py3-none-any.whl → 0.1.13.57__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.
- listpick/listpick_app.py +94 -195
- listpick/ui/footer.py +47 -34
- listpick/utils/utils.py +24 -50
- {listpick-0.1.13.55.dist-info → listpick-0.1.13.57.dist-info}/METADATA +1 -1
- {listpick-0.1.13.55.dist-info → listpick-0.1.13.57.dist-info}/RECORD +9 -12
- listpick/listpick_app_1.py +0 -3250
- listpick/lpapp2.py +0 -3153
- listpick/ui/footer_1.py +0 -213
- {listpick-0.1.13.55.dist-info → listpick-0.1.13.57.dist-info}/WHEEL +0 -0
- {listpick-0.1.13.55.dist-info → listpick-0.1.13.57.dist-info}/entry_points.txt +0 -0
- {listpick-0.1.13.55.dist-info → listpick-0.1.13.57.dist-info}/licenses/LICENSE.txt +0 -0
- {listpick-0.1.13.55.dist-info → listpick-0.1.13.57.dist-info}/top_level.txt +0 -0
listpick/listpick_app.py
CHANGED
|
@@ -140,7 +140,6 @@ class Picker:
|
|
|
140
140
|
footer_string_refresh_function: Optional[Callable] = None,
|
|
141
141
|
footer_timer: float=1,
|
|
142
142
|
get_footer_string_startup=False,
|
|
143
|
-
unicode_char_width: bool = True,
|
|
144
143
|
|
|
145
144
|
colours_start: int =0,
|
|
146
145
|
colours_end: int =-1,
|
|
@@ -257,7 +256,7 @@ class Picker:
|
|
|
257
256
|
self.footer_string_refresh_function = footer_string_refresh_function
|
|
258
257
|
self.footer_timer = footer_timer
|
|
259
258
|
self.get_footer_string_startup = get_footer_string_startup,
|
|
260
|
-
|
|
259
|
+
|
|
261
260
|
|
|
262
261
|
|
|
263
262
|
self.colours_start = colours_start
|
|
@@ -313,16 +312,16 @@ class Picker:
|
|
|
313
312
|
self.debug_level = debug_level
|
|
314
313
|
|
|
315
314
|
|
|
315
|
+
|
|
316
|
+
|
|
316
317
|
self.initialise_picker_state(reset_colours=self.reset_colours)
|
|
317
318
|
|
|
318
319
|
|
|
319
320
|
# Note: We have to set the footer after initialising the picker state so that the footer can use the get_function_data method
|
|
320
|
-
|
|
321
|
-
self.
|
|
322
|
-
# self.footer = self.footer_options[self.footer_style]
|
|
323
|
-
|
|
324
|
-
self.footer = CompactFooter(self.stdscr, colours_start, self.get_function_data)
|
|
321
|
+
self.footer_options = [StandardFooter(self.stdscr, colours_start, self.get_function_data), CompactFooter(self.stdscr, colours_start, self.get_function_data), NoFooter(self.stdscr, colours_start, self.get_function_data)]
|
|
322
|
+
self.footer = self.footer_options[self.footer_style]
|
|
325
323
|
|
|
324
|
+
# self.footer = CompactFooter(self.stdscr, colours_start, self.get_function_data)
|
|
326
325
|
|
|
327
326
|
|
|
328
327
|
def calculate_section_sizes(self):
|
|
@@ -385,6 +384,7 @@ class Picker:
|
|
|
385
384
|
def initialise_picker_state(self, reset_colours=False) -> None:
|
|
386
385
|
""" Initialise state variables for the picker. These are: debugging and colours. """
|
|
387
386
|
|
|
387
|
+
|
|
388
388
|
if curses.has_colors() and self.colours != None:
|
|
389
389
|
# raise Exception("Terminal does not support color")
|
|
390
390
|
curses.start_color()
|
|
@@ -474,6 +474,7 @@ class Picker:
|
|
|
474
474
|
|
|
475
475
|
if len(self.indexed_items) > 0 and len(self.indexed_items) >= self.cursor_pos and len(self.indexed_items[0][1]) >= self.id_column:
|
|
476
476
|
self.cursor_pos_id = self.indexed_items[self.cursor_pos][1][self.id_column]
|
|
477
|
+
self.cursor_pos_prev = self.cursor_pos
|
|
477
478
|
|
|
478
479
|
self.items, self.header = self.refresh_function()
|
|
479
480
|
|
|
@@ -597,8 +598,6 @@ class Picker:
|
|
|
597
598
|
else:
|
|
598
599
|
self.cursor_pos = 0
|
|
599
600
|
|
|
600
|
-
# if self.display_infobox:
|
|
601
|
-
# self.infobox_picker = self.infobox(self.stdscr, self.infobox_items, self.infobox_title)
|
|
602
601
|
|
|
603
602
|
|
|
604
603
|
def move_column(self, direction: int) -> None:
|
|
@@ -658,14 +657,15 @@ class Picker:
|
|
|
658
657
|
pass
|
|
659
658
|
self.stdscr.refresh()
|
|
660
659
|
|
|
661
|
-
def
|
|
662
|
-
""" Try-except wrapper for the draw_screen_
|
|
660
|
+
def draw_screen(self, indexed_items: list[Tuple[int, list[str]]], highlights: list[dict] = [{}], clear: bool = True) -> None:
|
|
661
|
+
""" Try-except wrapper for the draw_screen_ function. """
|
|
663
662
|
try:
|
|
664
|
-
self.
|
|
665
|
-
except:
|
|
666
|
-
self.logger.warning(f"
|
|
663
|
+
self.draw_screen_(self.indexed_items, self.highlights)
|
|
664
|
+
except Exception as e:
|
|
665
|
+
self.logger.warning(f"self.draw_screen_() error. {e}")
|
|
666
|
+
pass
|
|
667
667
|
|
|
668
|
-
def
|
|
668
|
+
def draw_screen_(self, indexed_items: list[Tuple[int, list[str]]], highlights: list[dict] = [{}], clear: bool = True) -> None:
|
|
669
669
|
""" Draw Picker screen. """
|
|
670
670
|
self.logger.debug("Draw screen.")
|
|
671
671
|
|
|
@@ -694,7 +694,7 @@ class Picker:
|
|
|
694
694
|
# rows = [v[1] for v in self.indexed_items] if len(self.indexed_items) else self.items
|
|
695
695
|
# Determine widths based only on the currently displayed indexed rows
|
|
696
696
|
rows = [v[1] for v in self.indexed_items[start_index:end_index]] if len(self.indexed_items) else self.items
|
|
697
|
-
self.column_widths = get_column_widths(rows, header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns, max_total_width=w
|
|
697
|
+
self.column_widths = get_column_widths(rows, header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns, max_total_width=w)
|
|
698
698
|
visible_column_widths = [c for i,c in enumerate(self.column_widths) if i not in self.hidden_columns]
|
|
699
699
|
visible_columns_total_width = sum(visible_column_widths) + len(self.separator)*(len(visible_column_widths)-1)
|
|
700
700
|
|
|
@@ -793,10 +793,10 @@ class Picker:
|
|
|
793
793
|
else:
|
|
794
794
|
cell_value = self.indexed_items[row][1][col] + self.separator
|
|
795
795
|
# cell_value = cell_value[:min(cell_width, cell_max_width)-len(self.separator)]
|
|
796
|
-
cell_value = truncate_to_display_width(cell_value, min(cell_width, cell_max_width)-len(self.separator)
|
|
796
|
+
cell_value = truncate_to_display_width(cell_value, min(cell_width, cell_max_width)-len(self.separator))
|
|
797
797
|
cell_value = cell_value + self.separator
|
|
798
798
|
# cell_value = cell_value
|
|
799
|
-
cell_value = truncate_to_display_width(cell_value, min(cell_width, cell_max_width)
|
|
799
|
+
cell_value = truncate_to_display_width(cell_value, min(cell_width, cell_max_width))
|
|
800
800
|
# row_str = truncate_to_display_width(row_str_left_adj, min(w-self.startx, visible_columns_total_width))
|
|
801
801
|
self.stdscr.addstr(y, cell_pos, cell_value, curses.color_pair(self.colours_start+colour_pair_number) | curses.A_BOLD)
|
|
802
802
|
# Part of the cell is on screen
|
|
@@ -838,7 +838,7 @@ class Picker:
|
|
|
838
838
|
def draw_highlights(highlights: list[dict], idx: int, y: int, item: tuple[int, list[str]]):
|
|
839
839
|
self.logger.debug(f"function: draw_highlights()")
|
|
840
840
|
if len(highlights) == 0: return None
|
|
841
|
-
full_row_str = format_row(item[1], self.hidden_columns, self.column_widths, self.separator, self.centre_in_cols
|
|
841
|
+
full_row_str = format_row(item[1], self.hidden_columns, self.column_widths, self.separator, self.centre_in_cols)
|
|
842
842
|
row_str = full_row_str[self.leftmost_char:]
|
|
843
843
|
for highlight in highlights:
|
|
844
844
|
if "row" in highlight:
|
|
@@ -854,13 +854,13 @@ class Picker:
|
|
|
854
854
|
continue
|
|
855
855
|
|
|
856
856
|
elif type(highlight["field"]) == type(0) and highlight["field"] not in self.hidden_columns:
|
|
857
|
-
match = re.search(highlight["match"], truncate_to_display_width(item[1][highlight["field"]], self.column_widths[highlight["field"]], centre=False
|
|
857
|
+
match = re.search(highlight["match"], truncate_to_display_width(item[1][highlight["field"]], self.column_widths[highlight["field"]], centre=False), re.IGNORECASE)
|
|
858
858
|
if not match: continue
|
|
859
859
|
field_start = sum([width for i, width in enumerate(self.column_widths[:highlight["field"]]) if i not in self.hidden_columns]) + sum([1 for i in range(highlight["field"]) if i not in self.hidden_columns])*wcswidth(self.separator)
|
|
860
860
|
|
|
861
861
|
## We want to search the non-centred values but highlight the centred values.
|
|
862
862
|
if self.centre_in_cols:
|
|
863
|
-
tmp = truncate_to_display_width(item[1][highlight["field"]], self.column_widths[highlight["field"]], self.centre_in_cols
|
|
863
|
+
tmp = truncate_to_display_width(item[1][highlight["field"]], self.column_widths[highlight["field"]], self.centre_in_cols)
|
|
864
864
|
field_start += (len(tmp) - len(tmp.lstrip()))
|
|
865
865
|
|
|
866
866
|
highlight_start = field_start + match.start()
|
|
@@ -882,11 +882,11 @@ class Picker:
|
|
|
882
882
|
item = self.indexed_items[idx]
|
|
883
883
|
y = idx - start_index + self.top_space
|
|
884
884
|
|
|
885
|
-
|
|
885
|
+
row_str = format_row(item[1], self.hidden_columns, self.column_widths, self.separator, self.centre_in_cols)[self.leftmost_char:]
|
|
886
886
|
# row_str = truncate_to_display_width(row_str, min(w-self.startx, visible_columns_total_width))
|
|
887
|
-
row_str_orig = format_row(item[1], self.hidden_columns, self.column_widths, self.separator, self.centre_in_cols
|
|
887
|
+
row_str_orig = format_row(item[1], self.hidden_columns, self.column_widths, self.separator, self.centre_in_cols)
|
|
888
888
|
row_str_left_adj = clip_left(row_str_orig, self.leftmost_char)
|
|
889
|
-
row_str = truncate_to_display_width(row_str_left_adj, min(w-self.startx, visible_columns_total_width)
|
|
889
|
+
row_str = truncate_to_display_width(row_str_left_adj, min(w-self.startx, visible_columns_total_width))
|
|
890
890
|
# row_str = truncate_to_display_width(row_str, min(w-self.startx, visible_columns_total_width))[self.leftmost_char:]
|
|
891
891
|
|
|
892
892
|
## Display the standard row
|
|
@@ -899,7 +899,7 @@ class Picker:
|
|
|
899
899
|
|
|
900
900
|
# Higlight cursor cell and selected cells
|
|
901
901
|
if self.cell_cursor:
|
|
902
|
-
|
|
902
|
+
self.selected_cells_by_row = get_selected_cells_by_row(self.cell_selections)
|
|
903
903
|
if item[0] in self.selected_cells_by_row:
|
|
904
904
|
for j in self.selected_cells_by_row[item[0]]:
|
|
905
905
|
highlight_cell(idx, j, visible_column_widths, colour_pair_number=25)
|
|
@@ -979,8 +979,6 @@ class Picker:
|
|
|
979
979
|
else:
|
|
980
980
|
self.stdscr.addstr(0,w-3," ", curses.color_pair(self.colours_start+23) | curses.A_BOLD)
|
|
981
981
|
|
|
982
|
-
# self.stdscr.refresh()
|
|
983
|
-
|
|
984
982
|
## Display footer
|
|
985
983
|
if self.show_footer:
|
|
986
984
|
# self.footer = NoFooter(self.stdscr, self.colours_start, self.get_function_data)
|
|
@@ -995,77 +993,11 @@ class Picker:
|
|
|
995
993
|
self.stdscr.addstr(h - 1, w-footer_string_width-1, " "*footer_string_width, curses.color_pair(self.colours_start+24))
|
|
996
994
|
self.stdscr.addstr(h - 1, w-footer_string_width-1, f"{disp_string}", curses.color_pair(self.colours_start+24))
|
|
997
995
|
|
|
998
|
-
|
|
999
|
-
self.stdscr.refresh()
|
|
1000
|
-
|
|
1001
996
|
## Display infobox
|
|
1002
997
|
if self.display_infobox:
|
|
1003
998
|
self.infobox(self.stdscr, message=self.infobox_items, title=self.infobox_title)
|
|
1004
999
|
# self.stdscr.timeout(2000) # timeout is set to 50 in order to get the infobox to be displayed so here we reset it to 2000
|
|
1005
|
-
# self.stdscr.refresh()
|
|
1006
1000
|
|
|
1007
|
-
# if self.display_infobox:
|
|
1008
|
-
# # self.stdscr.refresh()
|
|
1009
|
-
# # self.infobox(self.stdscr, message=self.infobox_items, title=self.infobox_title)
|
|
1010
|
-
#
|
|
1011
|
-
# infobox_width, infobox_height = w//2, 3*h//5
|
|
1012
|
-
# infobox_x, infobox_y = w - (infobox_width + 4), 3
|
|
1013
|
-
# self.infobox_picker.stdscr.mvwin(infobox_y, infobox_x)
|
|
1014
|
-
# self.infobox_picker.stdscr.resize(infobox_height, infobox_width)
|
|
1015
|
-
# self.infobox_picker.run()
|
|
1016
|
-
# self.infobox_picker.stdscr.noutrefresh()
|
|
1017
|
-
# else:
|
|
1018
|
-
# # self.stdscr.noutrefresh()
|
|
1019
|
-
# pass
|
|
1020
|
-
#
|
|
1021
|
-
#
|
|
1022
|
-
# if not self.display_only:
|
|
1023
|
-
# curses.doupdate()
|
|
1024
|
-
# self.stdscr.refresh()
|
|
1025
|
-
# pass
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
# def infobox___(self, stdscr: curses.window, message: list =[], title: str ="Infobox", colours_end: int = 0, duration: int = 4):
|
|
1029
|
-
# """ Display non-interactive infobox window. """
|
|
1030
|
-
#
|
|
1031
|
-
# self.logger.info(f"function: infobox()")
|
|
1032
|
-
# h, w = stdscr.getmaxyx()
|
|
1033
|
-
# notification_width, notification_height = w//2, 3*h//5
|
|
1034
|
-
# message_width = notification_width-5
|
|
1035
|
-
#
|
|
1036
|
-
# notification_x, notification_y = w-(notification_width+4), 3
|
|
1037
|
-
# if not message: message = "!!"
|
|
1038
|
-
# if isinstance(message, str):
|
|
1039
|
-
# submenu_items = [" "+message[i*message_width:(i+1)*message_width] for i in range(len(message)//message_width+1)]
|
|
1040
|
-
# else:
|
|
1041
|
-
# submenu_items = message
|
|
1042
|
-
#
|
|
1043
|
-
# notification_remap_keys = {
|
|
1044
|
-
# curses.KEY_RESIZE: curses.KEY_F5,
|
|
1045
|
-
# 27: ord('q')
|
|
1046
|
-
# }
|
|
1047
|
-
# if len(submenu_items) > notification_height - 2:
|
|
1048
|
-
# submenu_items = submenu_items[:notification_height-3] + [f"{'....':^{notification_width}}"]
|
|
1049
|
-
# # while True:
|
|
1050
|
-
# h, w = stdscr.getmaxyx()
|
|
1051
|
-
#
|
|
1052
|
-
# submenu_win = self.stdscr.derwin(notification_height, notification_width, 3, w - (notification_width+4))
|
|
1053
|
-
# infobox_data = {
|
|
1054
|
-
# "items": submenu_items,
|
|
1055
|
-
# "colours": notification_colours,
|
|
1056
|
-
# "colours_start": self.notification_colours_start,
|
|
1057
|
-
# "disabled_keys": [ord('z'), ord('c')],
|
|
1058
|
-
# "show_footer": False,
|
|
1059
|
-
# "top_gap": 0,
|
|
1060
|
-
# "key_remappings": notification_remap_keys,
|
|
1061
|
-
# "display_only": True,
|
|
1062
|
-
# "hidden_columns": [],
|
|
1063
|
-
# "title": title,
|
|
1064
|
-
# "reset_colours": False,
|
|
1065
|
-
# }
|
|
1066
|
-
# submenu_win.noutrefresh()
|
|
1067
|
-
# OptionPicker = Picker(submenu_win, **infobox_data)
|
|
1068
|
-
# return OptionPicker
|
|
1069
1001
|
|
|
1070
1002
|
|
|
1071
1003
|
def infobox(self, stdscr: curses.window, message: str ="", title: str ="Infobox", colours_end: int = 0, duration: int = 4) -> curses.window:
|
|
@@ -1208,7 +1140,6 @@ class Picker:
|
|
|
1208
1140
|
"debug": self.debug,
|
|
1209
1141
|
"debug_level": self.debug_level,
|
|
1210
1142
|
"reset_colours": self.reset_colours,
|
|
1211
|
-
"unicode_char_width": self.unicode_char_width,
|
|
1212
1143
|
}
|
|
1213
1144
|
return function_data
|
|
1214
1145
|
|
|
@@ -1307,7 +1238,7 @@ class Picker:
|
|
|
1307
1238
|
while True:
|
|
1308
1239
|
h, w = stdscr.getmaxyx()
|
|
1309
1240
|
|
|
1310
|
-
choose_opts_widths = get_column_widths(options
|
|
1241
|
+
choose_opts_widths = get_column_widths(options)
|
|
1311
1242
|
window_width = min(max(sum(choose_opts_widths) + 6, 50) + 6, w)
|
|
1312
1243
|
window_height = min(h//2, max(6, len(options)+3))
|
|
1313
1244
|
|
|
@@ -1462,8 +1393,6 @@ class Picker:
|
|
|
1462
1393
|
self.initialise_variables()
|
|
1463
1394
|
elif setting == "pc":
|
|
1464
1395
|
self.pin_cursor = not self.pin_cursor
|
|
1465
|
-
elif setting == "unicode":
|
|
1466
|
-
self.unicode_char_width = not self.unicode_char_width
|
|
1467
1396
|
|
|
1468
1397
|
elif setting.startswith("ft"):
|
|
1469
1398
|
if len(setting) > 2 and setting[2:].isnumeric():
|
|
@@ -1527,6 +1456,7 @@ class Picker:
|
|
|
1527
1456
|
self.draw_screen(self.indexed_items, self.highlights)
|
|
1528
1457
|
self.notification(self.stdscr, message=f"Theme {self.colour_theme_number} applied.")
|
|
1529
1458
|
|
|
1459
|
+
|
|
1530
1460
|
else:
|
|
1531
1461
|
self.user_settings = ""
|
|
1532
1462
|
return None
|
|
@@ -1550,6 +1480,7 @@ class Picker:
|
|
|
1550
1480
|
""" Toggle selection of item at index. """
|
|
1551
1481
|
self.logger.info(f"function: toggle_item()")
|
|
1552
1482
|
self.selections[index] = not self.selections[index]
|
|
1483
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
1553
1484
|
|
|
1554
1485
|
def select_all(self) -> None:
|
|
1555
1486
|
""" Select all in indexed_items. """
|
|
@@ -1558,8 +1489,8 @@ class Picker:
|
|
|
1558
1489
|
self.selections[self.indexed_items[i][0]] = True
|
|
1559
1490
|
for i in self.cell_selections.keys():
|
|
1560
1491
|
self.cell_selections[i] = True
|
|
1561
|
-
|
|
1562
|
-
|
|
1492
|
+
|
|
1493
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
1563
1494
|
|
|
1564
1495
|
def deselect_all(self) -> None:
|
|
1565
1496
|
""" Deselect all items in indexed_items. """
|
|
@@ -1568,7 +1499,7 @@ class Picker:
|
|
|
1568
1499
|
self.selections[i] = False
|
|
1569
1500
|
for i in self.cell_selections.keys():
|
|
1570
1501
|
self.cell_selections[i] = False
|
|
1571
|
-
self.
|
|
1502
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
1572
1503
|
|
|
1573
1504
|
def handle_visual_selection(self, selecting:bool = True) -> None:
|
|
1574
1505
|
""" Toggle visual selection or deselection. """
|
|
@@ -1596,22 +1527,15 @@ class Picker:
|
|
|
1596
1527
|
xend = max(self.start_selection_col, self.selected_column)
|
|
1597
1528
|
for i in range(ystart, yend + 1):
|
|
1598
1529
|
if self.indexed_items[i][0] not in self.unselectable_indices:
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
self.selected_cells_by_row[row] = []
|
|
1602
|
-
|
|
1603
|
-
for col in range(xstart, xend+1):
|
|
1604
|
-
cell_index = (row, col)
|
|
1530
|
+
for j in range(xstart, xend+1):
|
|
1531
|
+
cell_index = (self.indexed_items[i][0], j)
|
|
1605
1532
|
self.cell_selections[cell_index] = True
|
|
1606
|
-
|
|
1607
|
-
self.selected_cells_by_row[row].append(col)
|
|
1608
|
-
# Remove duplicates
|
|
1609
|
-
self.selected_cells_by_row[row] = list(set(self.selected_cells_by_row[row]))
|
|
1610
|
-
|
|
1611
1533
|
self.start_selection = -1
|
|
1612
1534
|
self.end_selection = -1
|
|
1613
1535
|
self.is_selecting = False
|
|
1614
1536
|
|
|
1537
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
1538
|
+
|
|
1615
1539
|
elif self.is_deselecting:
|
|
1616
1540
|
self.end_selection = self.indexed_items[self.cursor_pos][0]
|
|
1617
1541
|
self.end_selection = self.cursor_pos
|
|
@@ -1627,22 +1551,14 @@ class Picker:
|
|
|
1627
1551
|
xstart = min(self.start_selection_col, self.selected_column)
|
|
1628
1552
|
xend = max(self.start_selection_col, self.selected_column)
|
|
1629
1553
|
for i in range(ystart, yend + 1):
|
|
1630
|
-
row = self.indexed_items[i][0]
|
|
1631
1554
|
if self.indexed_items[i][0] not in self.unselectable_indices:
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
self.selected_cells_by_row[row].remove(col)
|
|
1636
|
-
except:
|
|
1637
|
-
pass
|
|
1638
|
-
cell_index = (row, col)
|
|
1639
|
-
self.cell_selections[cell_index] = False
|
|
1640
|
-
if self.selected_cells_by_row[row] == []:
|
|
1641
|
-
del self.selected_cells_by_row[row]
|
|
1642
|
-
|
|
1555
|
+
for j in range(xstart, xend+1):
|
|
1556
|
+
cell_index = (self.indexed_items[i][0], j)
|
|
1557
|
+
self.cell_selections[cell_index] = False
|
|
1643
1558
|
self.start_selection = -1
|
|
1644
1559
|
self.end_selection = -1
|
|
1645
1560
|
self.is_deselecting = False
|
|
1561
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
1646
1562
|
|
|
1647
1563
|
def cursor_down(self, count=1) -> bool:
|
|
1648
1564
|
""" Move cursor down. """
|
|
@@ -1760,6 +1676,7 @@ class Picker:
|
|
|
1760
1676
|
if not acceptable_data_type:
|
|
1761
1677
|
break
|
|
1762
1678
|
if not acceptable_data_type:
|
|
1679
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
1763
1680
|
self.notification(self.stdscr, message="Error pasting data.")
|
|
1764
1681
|
return None
|
|
1765
1682
|
|
|
@@ -1870,7 +1787,6 @@ class Picker:
|
|
|
1870
1787
|
with self.data_lock:
|
|
1871
1788
|
self.items, self.header = tmp_items, tmp_header
|
|
1872
1789
|
self.data_ready = True
|
|
1873
|
-
self.draw_screen(self.indexed_items, self.highlights)
|
|
1874
1790
|
|
|
1875
1791
|
def save_input_history(self, file_path: str) -> bool:
|
|
1876
1792
|
""" Save input field history. Returns True if successful save. """
|
|
@@ -1917,7 +1833,7 @@ class Picker:
|
|
|
1917
1833
|
|
|
1918
1834
|
def get_word_list(self) -> list[str]:
|
|
1919
1835
|
""" Get a list of all words used in any cell of the picker. Used for completion in search/filter input_field. """
|
|
1920
|
-
self.logger.info(f"function:
|
|
1836
|
+
self.logger.info(f"function: infobox()")
|
|
1921
1837
|
translator = str.maketrans('', '', string.punctuation)
|
|
1922
1838
|
|
|
1923
1839
|
words = []
|
|
@@ -2018,7 +1934,8 @@ class Picker:
|
|
|
2018
1934
|
|
|
2019
1935
|
if self.display_only:
|
|
2020
1936
|
self.stdscr.refresh()
|
|
2021
|
-
|
|
1937
|
+
function_data = self.get_function_data()
|
|
1938
|
+
return [], "", function_data
|
|
2022
1939
|
|
|
2023
1940
|
# Main loop
|
|
2024
1941
|
|
|
@@ -2039,7 +1956,7 @@ class Picker:
|
|
|
2039
1956
|
initial_time = time.time()
|
|
2040
1957
|
|
|
2041
1958
|
self.draw_screen(self.indexed_items, self.highlights, clear=False)
|
|
2042
|
-
|
|
1959
|
+
|
|
2043
1960
|
self.refreshing_data = False
|
|
2044
1961
|
self.data_ready = False
|
|
2045
1962
|
|
|
@@ -2159,7 +2076,6 @@ class Picker:
|
|
|
2159
2076
|
options += [["rh", "Toggle row header"]]
|
|
2160
2077
|
options += [["modes", "Toggle modes"]]
|
|
2161
2078
|
options += [["ft", "Cycle through footer styles (accepts ft#)"]]
|
|
2162
|
-
options += [["unicode", "Toggle b/w using len and wcwidth to calculate char width."]]
|
|
2163
2079
|
options += [[f"s{i}", f"Select col. {i}"] for i in range(len(self.items[0]))]
|
|
2164
2080
|
options += [[f"!{i}", f"Toggle col. {i}"] for i in range(len(self.items[0]))]
|
|
2165
2081
|
options += [["ara", "Add empty row after cursor."]]
|
|
@@ -2224,31 +2140,11 @@ class Picker:
|
|
|
2224
2140
|
if len(self.indexed_items) > 0:
|
|
2225
2141
|
item_index = self.indexed_items[self.cursor_pos][0]
|
|
2226
2142
|
cell_index = (self.indexed_items[self.cursor_pos][0], self.selected_column)
|
|
2227
|
-
row, col = cell_index
|
|
2228
2143
|
selected_count = sum(self.selections.values())
|
|
2229
2144
|
if self.max_selected == -1 or selected_count >= self.max_selected:
|
|
2230
2145
|
self.toggle_item(item_index)
|
|
2231
2146
|
|
|
2232
2147
|
self.cell_selections[cell_index] = not self.cell_selections[cell_index]
|
|
2233
|
-
## Set self.selected_cells_by_row
|
|
2234
|
-
# If any cells in the current row are selected
|
|
2235
|
-
if row in self.selected_cells_by_row:
|
|
2236
|
-
# If the current cell is selected then remove it
|
|
2237
|
-
if col in self.selected_cells_by_row[row]:
|
|
2238
|
-
# If the current cell is the only cell in the row that is selected then remove the row from the dict
|
|
2239
|
-
if len(self.selected_cells_by_row[row]) == 1:
|
|
2240
|
-
|
|
2241
|
-
del self.selected_cells_by_row[row]
|
|
2242
|
-
# else remove only the index of the current cell
|
|
2243
|
-
else:
|
|
2244
|
-
self.selected_cells_by_row[row].remove(col)
|
|
2245
|
-
# If there are cells in the row that are selected then append the current cell to the row
|
|
2246
|
-
else:
|
|
2247
|
-
self.selected_cells_by_row[row].append(col)
|
|
2248
|
-
# Add the a list containing only the current column
|
|
2249
|
-
else:
|
|
2250
|
-
self.selected_cells_by_row[row] = [col]
|
|
2251
|
-
|
|
2252
2148
|
self.cursor_down()
|
|
2253
2149
|
elif self.check_key("select_all", key, self.keys_dict): # Select all (m or ctrl-a)
|
|
2254
2150
|
self.select_all()
|
|
@@ -2264,6 +2160,8 @@ class Picker:
|
|
|
2264
2160
|
if new_pos < len(self.indexed_items):
|
|
2265
2161
|
self.cursor_pos = new_pos
|
|
2266
2162
|
|
|
2163
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
2164
|
+
|
|
2267
2165
|
elif self.check_key("cursor_bottom", key, self.keys_dict):
|
|
2268
2166
|
new_pos = len(self.indexed_items)-1
|
|
2269
2167
|
while True:
|
|
@@ -2271,7 +2169,12 @@ class Picker:
|
|
|
2271
2169
|
else: break
|
|
2272
2170
|
if new_pos < len(self.items) and new_pos >= 0:
|
|
2273
2171
|
self.cursor_pos = new_pos
|
|
2274
|
-
|
|
2172
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
2173
|
+
# current_row = items_per_page - 1
|
|
2174
|
+
# if current_page + 1 == (len(self.indexed_items) + items_per_page - 1) // items_per_page:
|
|
2175
|
+
#
|
|
2176
|
+
# current_row = (len(self.indexed_items) +items_per_page - 1) % items_per_page
|
|
2177
|
+
# self.draw_screen(self.indexed_items, self.highlights)
|
|
2275
2178
|
elif self.check_key("enter", key, self.keys_dict):
|
|
2276
2179
|
self.logger.info(f"key_function enter")
|
|
2277
2180
|
# Print the selected indices if any, otherwise print the current index
|
|
@@ -2351,6 +2254,7 @@ class Picker:
|
|
|
2351
2254
|
if len(self.indexed_items) > 0:
|
|
2352
2255
|
current_index = self.indexed_items[self.cursor_pos][0]
|
|
2353
2256
|
sort_items(self.indexed_items, sort_method=self.columns_sort_method[self.sort_column], sort_column=self.sort_column, sort_reverse=self.sort_reverse[self.sort_column]) # Re-sort self.items based on new column
|
|
2257
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
2354
2258
|
self.cursor_pos = [row[0] for row in self.indexed_items].index(current_index)
|
|
2355
2259
|
self.logger.info(f"key_function cycle_sort_order. (sort_column, sort_method, sort_reverse) = ({self.sort_column}, {self.columns_sort_method[self.sort_column]}, {self.sort_reverse[self.sort_column]})")
|
|
2356
2260
|
elif self.check_key("col_select", key, self.keys_dict):
|
|
@@ -2374,7 +2278,7 @@ class Picker:
|
|
|
2374
2278
|
|
|
2375
2279
|
## Scroll with column select
|
|
2376
2280
|
rows = self.get_visible_rows()
|
|
2377
|
-
self.column_widths = get_column_widths(rows, header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns, max_total_width=w
|
|
2281
|
+
self.column_widths = get_column_widths(rows, header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns, max_total_width=w)
|
|
2378
2282
|
visible_column_widths = [c for i,c in enumerate(self.column_widths) if i not in self.hidden_columns]
|
|
2379
2283
|
column_set_width = sum(visible_column_widths)+len(self.separator)*len(visible_column_widths)
|
|
2380
2284
|
start_of_cell = sum(visible_column_widths[:self.selected_column])+len(self.separator)*self.selected_column
|
|
@@ -2401,7 +2305,8 @@ class Picker:
|
|
|
2401
2305
|
|
|
2402
2306
|
## Scroll with column select
|
|
2403
2307
|
rows = self.get_visible_rows()
|
|
2404
|
-
self.column_widths = get_column_widths(rows, header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns, max_total_width=w
|
|
2308
|
+
self.column_widths = get_column_widths(rows, header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns, max_total_width=w)
|
|
2309
|
+
|
|
2405
2310
|
visible_column_widths = [c for i,c in enumerate(self.column_widths) if i not in self.hidden_columns]
|
|
2406
2311
|
column_set_width = sum(visible_column_widths)+len(self.separator)*len(visible_column_widths)
|
|
2407
2312
|
start_of_cell = sum(visible_column_widths[:self.selected_column])+len(self.separator)*self.selected_column
|
|
@@ -2416,13 +2321,18 @@ class Picker:
|
|
|
2416
2321
|
self.leftmost_char = start_of_cell
|
|
2417
2322
|
|
|
2418
2323
|
self.leftmost_char = max(0, min(column_set_width - display_width + 5, self.leftmost_char))
|
|
2419
|
-
|
|
2324
|
+
#
|
|
2420
2325
|
elif self.check_key("scroll_right", key, self.keys_dict):
|
|
2421
2326
|
self.logger.info(f"key_function scroll_right")
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2327
|
+
rows = self.get_visible_rows()
|
|
2328
|
+
longest_row_str_len = 0
|
|
2329
|
+
for i in range(len(rows)):
|
|
2330
|
+
item = rows[i]
|
|
2331
|
+
row_str = format_row(item, self.hidden_columns, self.column_widths, self.separator, self.centre_in_cols)[self.leftmost_char:]
|
|
2332
|
+
if len(row_str) > longest_row_str_len: longest_row_str_len=len(row_str)
|
|
2333
|
+
|
|
2334
|
+
if longest_row_str_len >= w-self.startx:
|
|
2335
|
+
self.leftmost_char = self.leftmost_char+5
|
|
2426
2336
|
|
|
2427
2337
|
elif self.check_key("scroll_left", key, self.keys_dict):
|
|
2428
2338
|
self.logger.info(f"key_function scroll_left")
|
|
@@ -2439,7 +2349,7 @@ class Picker:
|
|
|
2439
2349
|
rows = self.get_visible_rows()
|
|
2440
2350
|
for i in range(len(rows)):
|
|
2441
2351
|
item = rows[i]
|
|
2442
|
-
row_str = format_row(item, self.hidden_columns, self.column_widths, self.separator, self.centre_in_cols
|
|
2352
|
+
row_str = format_row(item, self.hidden_columns, self.column_widths, self.separator, self.centre_in_cols)
|
|
2443
2353
|
if len(row_str) > longest_row_str_len: longest_row_str_len=len(row_str)
|
|
2444
2354
|
# for i in range(len(self.indexed_items)):
|
|
2445
2355
|
# item = self.indexed_items[i]
|
|
@@ -2510,37 +2420,44 @@ class Picker:
|
|
|
2510
2420
|
|
|
2511
2421
|
# elif self.check_key("increase_lines_per_page", key, self.keys_dict):
|
|
2512
2422
|
# self.items_per_page += 1
|
|
2423
|
+
# self.draw_screen(self.indexed_items, self.highlights)
|
|
2513
2424
|
# elif self.check_key("decrease_lines_per_page", key, self.keys_dict):
|
|
2514
2425
|
# if self.items_per_page > 1:
|
|
2515
2426
|
# self.items_per_page -= 1
|
|
2516
|
-
|
|
2427
|
+
# self.draw_screen(self.indexed_items, self.highlights)
|
|
2517
2428
|
elif self.check_key("decrease_column_width", key, self.keys_dict):
|
|
2518
2429
|
self.logger.info(f"key_function decrease_column_width")
|
|
2519
2430
|
if self.max_column_width > 10:
|
|
2520
2431
|
self.max_column_width -= 10
|
|
2521
2432
|
# self.column_widths = get_column_widths(self.items, header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns, max_total_width=2)
|
|
2433
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
2522
2434
|
elif self.check_key("increase_column_width", key, self.keys_dict):
|
|
2523
2435
|
self.logger.info(f"key_function increase_column_width")
|
|
2524
2436
|
if self.max_column_width < 1000:
|
|
2525
2437
|
self.max_column_width += 10
|
|
2526
2438
|
# self.column_widths = get_column_widths(self.items, header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns, max_total_width=w)
|
|
2439
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
2527
2440
|
elif self.check_key("visual_selection_toggle", key, self.keys_dict):
|
|
2528
2441
|
self.logger.info(f"key_function visual_selection_toggle")
|
|
2529
2442
|
self.handle_visual_selection()
|
|
2443
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
2530
2444
|
|
|
2531
2445
|
elif self.check_key("visual_deselection_toggle", key, self.keys_dict):
|
|
2532
2446
|
self.logger.info(f"key_function visual_deselection_toggle")
|
|
2533
2447
|
self.handle_visual_selection(selecting=False)
|
|
2448
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
2534
2449
|
|
|
2535
2450
|
elif key == curses.KEY_RESIZE: # Terminal resize signal
|
|
2536
2451
|
|
|
2537
2452
|
self.calculate_section_sizes()
|
|
2538
|
-
self.column_widths = get_column_widths(self.items, header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns, max_total_width=w
|
|
2453
|
+
self.column_widths = get_column_widths(self.items, header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns, max_total_width=w)
|
|
2539
2454
|
|
|
2455
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
2540
2456
|
|
|
2541
2457
|
|
|
2542
2458
|
elif self.check_key("filter_input", key, self.keys_dict):
|
|
2543
2459
|
self.logger.info(f"key_function filter_input")
|
|
2460
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
2544
2461
|
usrtxt = f"{self.filter_query} " if self.filter_query else ""
|
|
2545
2462
|
field_end_f = lambda: self.stdscr.getmaxyx()[1]-38 if self.show_footer else lambda: self.stdscr.getmaxyx()[1]-3
|
|
2546
2463
|
if self.show_footer and self.footer.height >= 2: field_end_f = lambda: self.stdscr.getmaxyx()[1]-38
|
|
@@ -2585,6 +2502,7 @@ class Picker:
|
|
|
2585
2502
|
|
|
2586
2503
|
elif self.check_key("search_input", key, self.keys_dict):
|
|
2587
2504
|
self.logger.info(f"key_function search_input")
|
|
2505
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
2588
2506
|
usrtxt = f"{self.search_query} " if self.search_query else ""
|
|
2589
2507
|
field_end_f = lambda: self.stdscr.getmaxyx()[1]-38 if self.show_footer else lambda: self.stdscr.getmaxyx()[1]-3
|
|
2590
2508
|
if self.show_footer and self.footer.height >= 3: field_end_f = lambda: self.stdscr.getmaxyx()[1]-38
|
|
@@ -2692,6 +2610,7 @@ class Picker:
|
|
|
2692
2610
|
# self.mode_index = 0
|
|
2693
2611
|
# self.highlights = [highlight for highlight in self.highlights if "type" not in highlight or highlight["type"] != "search" ]
|
|
2694
2612
|
# continue
|
|
2613
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
2695
2614
|
|
|
2696
2615
|
elif self.check_key("opts_input", key, self.keys_dict):
|
|
2697
2616
|
self.logger.info(f"key_function opts_input")
|
|
@@ -2930,12 +2849,9 @@ class Picker:
|
|
|
2930
2849
|
self.stdscr.clear()
|
|
2931
2850
|
self.stdscr.refresh()
|
|
2932
2851
|
self.initialise_variables()
|
|
2852
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
2933
2853
|
|
|
2934
2854
|
|
|
2935
|
-
# The refresh symbol colour is not updated when the data is retrieved so remains white until a key is pressed.
|
|
2936
|
-
# if key != -1:
|
|
2937
|
-
# self.draw_screen(self.indexed_items, self.highlights, clear=clear_screen)
|
|
2938
|
-
|
|
2939
2855
|
|
|
2940
2856
|
self.draw_screen(self.indexed_items, self.highlights, clear=clear_screen)
|
|
2941
2857
|
|
|
@@ -3177,28 +3093,21 @@ def main() -> None:
|
|
|
3177
3093
|
pass
|
|
3178
3094
|
|
|
3179
3095
|
function_data["colour_theme_number"] = 3
|
|
3180
|
-
function_data["modes"] = [
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
]
|
|
3195
|
-
highlights = [
|
|
3196
|
-
{
|
|
3197
|
-
"field": 1,
|
|
3198
|
-
"match": "a",
|
|
3199
|
-
"color": 8,
|
|
3200
|
-
}
|
|
3201
|
-
]
|
|
3096
|
+
# function_data["modes"] = [
|
|
3097
|
+
# {
|
|
3098
|
+
# 'filter': '',
|
|
3099
|
+
# 'sort': 0,
|
|
3100
|
+
# 'name': 'All',
|
|
3101
|
+
# },
|
|
3102
|
+
# {
|
|
3103
|
+
# 'filter': '--2 miss',
|
|
3104
|
+
# 'name': 'miss',
|
|
3105
|
+
# },
|
|
3106
|
+
# {
|
|
3107
|
+
# 'filter': '--2 mp4',
|
|
3108
|
+
# 'name': 'mp4',
|
|
3109
|
+
# },
|
|
3110
|
+
# ]
|
|
3202
3111
|
function_data["cell_cursor"] = True
|
|
3203
3112
|
function_data["display_modes"] = True
|
|
3204
3113
|
function_data["centre_in_cols"] = True
|
|
@@ -3209,19 +3118,9 @@ def main() -> None:
|
|
|
3209
3118
|
function_data["centre_in_terminal_vertical"] = True
|
|
3210
3119
|
function_data["highlight_full_row"] = True
|
|
3211
3120
|
function_data["pin_cursor"] = True
|
|
3212
|
-
function_data["display_infobox"] = True
|
|
3213
|
-
function_data["infobox_items"] = [["1"], ["2"], ["3"]]
|
|
3214
|
-
function_data["infobox_title"] = "Title"
|
|
3215
|
-
function_data["footer_string"] = "Title"
|
|
3216
|
-
function_data["highlights"] = highlights
|
|
3217
|
-
function_data["show_footer"] = False
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
3121
|
# function_data["debug"] = True
|
|
3221
3122
|
# function_data["debug_level"] = 1
|
|
3222
3123
|
stdscr = start_curses()
|
|
3223
|
-
# h, w = stdscr.getmaxyx()
|
|
3224
|
-
# win = stdscr.derwin(h, w//2, 0, 0)
|
|
3225
3124
|
try:
|
|
3226
3125
|
# Run the Picker
|
|
3227
3126
|
# h, w = stdscr.getmaxyx()
|