listpick 0.1.13.24__tar.gz → 0.1.13.26__tar.gz
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-0.1.13.24 → listpick-0.1.13.26}/CHANGELOG.md +1 -0
- {listpick-0.1.13.24/src/listpick.egg-info → listpick-0.1.13.26}/PKG-INFO +1 -1
- {listpick-0.1.13.24 → listpick-0.1.13.26}/setup.py +1 -1
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/listpick_app.py +73 -25
- {listpick-0.1.13.24 → listpick-0.1.13.26/src/listpick.egg-info}/PKG-INFO +1 -1
- {listpick-0.1.13.24 → listpick-0.1.13.26}/.gitignore +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/LICENSE.txt +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/README.md +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/TODO.md +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/assets/aria2tui_screenshot.png +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/assets/file_compare.png +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/assets/lpfman.png +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/footer_string_example.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/input.toml +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/input.txt +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/list_files.toml +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/list_files_empty.toml +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/picker_example.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/setup.cfg +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/template.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/video_duplicates.toml +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/listpick.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/requirements.txt +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/setup.cfg +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/__init__.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/__main__.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/__init__.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/build_help.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/footer.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/help_screen.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/input_field.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/keys.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/pane_stuff.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/picker_colours.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/__init__.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/clipboard_operations.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/config.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/dump.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/filtering.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/generate_data.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/options_selectors.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/paste_operations.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/picker_log.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/search_and_filter_utils.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/searching.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/sorting.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/table_to_list_of_lists.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/utils.py +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick.egg-info/SOURCES.txt +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick.egg-info/dependency_links.txt +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick.egg-info/entry_points.txt +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick.egg-info/requires.txt +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick.egg-info/top_level.txt +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/tests/kitty_control.sh +0 -0
- {listpick-0.1.13.24 → listpick-0.1.13.26}/tests/sorting_dates.csv +0 -0
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
- Added pin_cursor options which keeps the cursor on the same row during a refresh rather than tracking the id of the highlighted row.
|
|
27
27
|
- Updated StandardFooter. Now shows information on two lines rather than three; all cursor and selection information on the first line and the sort information on the second. Cursor, Visual (de)selection now abreviated to C, VS, and VDS.
|
|
28
28
|
- Fixed flickering when displaying an infobox.
|
|
29
|
+
- Optimised cpu usage by created a class variable selected_cells_by_row which updates with selection/deselection rather than being determined each time the draw_screen loop is run.
|
|
29
30
|
|
|
30
31
|
## [0.1.13] 2025-07-28
|
|
31
32
|
- Cell-based picker is now supported.
|
|
@@ -16,7 +16,7 @@ with open("README.md", "r", encoding = "utf-8") as fh:
|
|
|
16
16
|
|
|
17
17
|
setuptools.setup(
|
|
18
18
|
name = "listpick",
|
|
19
|
-
version = "0.1.13.
|
|
19
|
+
version = "0.1.13.26",
|
|
20
20
|
author = "Grim",
|
|
21
21
|
author_email = "grimandgreedy@protonmail.com",
|
|
22
22
|
description = "Listpick is a powerful TUI data tool for creating TUI apps or viewing/comparing tabulated data.",
|
|
@@ -324,6 +324,7 @@ class Picker:
|
|
|
324
324
|
# self.footer = CompactFooter(self.stdscr, colours_start, self.get_function_data)
|
|
325
325
|
|
|
326
326
|
|
|
327
|
+
|
|
327
328
|
def calculate_section_sizes(self):
|
|
328
329
|
"""
|
|
329
330
|
Calculte the following for the Picker:
|
|
@@ -598,6 +599,8 @@ class Picker:
|
|
|
598
599
|
else:
|
|
599
600
|
self.cursor_pos = 0
|
|
600
601
|
|
|
602
|
+
if self.display_infobox:
|
|
603
|
+
self.infobox_picker = self.infobox(self.stdscr, self.infobox_items, self.infobox_title)
|
|
601
604
|
|
|
602
605
|
|
|
603
606
|
def move_column(self, direction: int) -> None:
|
|
@@ -891,7 +894,7 @@ class Picker:
|
|
|
891
894
|
|
|
892
895
|
# Higlight cursor cell and selected cells
|
|
893
896
|
if self.cell_cursor:
|
|
894
|
-
self.selected_cells_by_row = get_selected_cells_by_row(self.cell_selections)
|
|
897
|
+
# self.selected_cells_by_row = get_selected_cells_by_row(self.cell_selections)
|
|
895
898
|
if item[0] in self.selected_cells_by_row:
|
|
896
899
|
for j in self.selected_cells_by_row[item[0]]:
|
|
897
900
|
highlight_cell(idx, j, visible_column_widths, colour_pair_number=25)
|
|
@@ -987,15 +990,24 @@ class Picker:
|
|
|
987
990
|
|
|
988
991
|
## Display infobox
|
|
989
992
|
if self.display_infobox:
|
|
990
|
-
self.
|
|
993
|
+
# self.stdscr.refresh()
|
|
994
|
+
# self.infobox(self.stdscr, message=self.infobox_items, title=self.infobox_title)
|
|
995
|
+
|
|
996
|
+
infobox_width, infobox_height = w//2, 3*h//5
|
|
997
|
+
infobox_x, infobox_y = w - (infobox_width + 4), 3
|
|
998
|
+
self.infobox_picker.stdscr.mvwin(infobox_y, infobox_x)
|
|
999
|
+
self.infobox_picker.stdscr.resize(infobox_height, infobox_width)
|
|
1000
|
+
self.infobox_picker.run()
|
|
1001
|
+
self.infobox_picker.stdscr.noutrefresh()
|
|
1002
|
+
else:
|
|
1003
|
+
self.stdscr.noutrefresh()
|
|
991
1004
|
|
|
992
|
-
# if not self.display_only:
|
|
993
|
-
# self.stdscr.refresh()
|
|
994
|
-
# 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
|
|
995
1005
|
|
|
1006
|
+
if not self.display_only:
|
|
1007
|
+
curses.doupdate()
|
|
996
1008
|
|
|
997
1009
|
|
|
998
|
-
def infobox(self, stdscr: curses.window, message:
|
|
1010
|
+
def infobox(self, stdscr: curses.window, message: list =[], title: str ="Infobox", colours_end: int = 0, duration: int = 4):
|
|
999
1011
|
""" Display non-interactive infobox window. """
|
|
1000
1012
|
|
|
1001
1013
|
self.logger.info(f"function: infobox()")
|
|
@@ -1003,6 +1015,7 @@ class Picker:
|
|
|
1003
1015
|
notification_width, notification_height = w//2, 3*h//5
|
|
1004
1016
|
message_width = notification_width-5
|
|
1005
1017
|
|
|
1018
|
+
notification_x, notification_y = w-(notification_width+4), 3
|
|
1006
1019
|
if not message: message = "!!"
|
|
1007
1020
|
if isinstance(message, str):
|
|
1008
1021
|
submenu_items = [" "+message[i*message_width:(i+1)*message_width] for i in range(len(message)//message_width+1)]
|
|
@@ -1018,10 +1031,7 @@ class Picker:
|
|
|
1018
1031
|
# while True:
|
|
1019
1032
|
h, w = stdscr.getmaxyx()
|
|
1020
1033
|
|
|
1021
|
-
|
|
1022
|
-
submenu_win = self.stdscr.subpad(notification_height, notification_width, 3, w - (notification_width+4))
|
|
1023
|
-
submenu_win.erase()
|
|
1024
|
-
# submenu_win.untouchwin()
|
|
1034
|
+
submenu_win = self.stdscr.derwin(notification_height, notification_width, 3, w - (notification_width+4))
|
|
1025
1035
|
infobox_data = {
|
|
1026
1036
|
"items": submenu_items,
|
|
1027
1037
|
"colours": notification_colours,
|
|
@@ -1035,12 +1045,9 @@ class Picker:
|
|
|
1035
1045
|
"title": title,
|
|
1036
1046
|
"reset_colours": False,
|
|
1037
1047
|
}
|
|
1038
|
-
|
|
1039
|
-
# for i in range(3, 3+notification_height):
|
|
1040
|
-
# self.stdscr.addstr(i, w - (notification_width+4), ' '*notification_width, curses.color_pair(4))
|
|
1048
|
+
submenu_win.noutrefresh()
|
|
1041
1049
|
OptionPicker = Picker(submenu_win, **infobox_data)
|
|
1042
|
-
|
|
1043
|
-
submenu_win.refresh()
|
|
1050
|
+
return OptionPicker
|
|
1044
1051
|
|
|
1045
1052
|
|
|
1046
1053
|
def get_function_data(self) -> dict:
|
|
@@ -1488,6 +1495,10 @@ class Picker:
|
|
|
1488
1495
|
self.selections[self.indexed_items[i][0]] = True
|
|
1489
1496
|
for i in self.cell_selections.keys():
|
|
1490
1497
|
self.cell_selections[i] = True
|
|
1498
|
+
for row in range(len(self.indexed_items)):
|
|
1499
|
+
self.selected_cells_by_row[row] = list(range(len(self.indexed_items[row][1])))
|
|
1500
|
+
|
|
1501
|
+
|
|
1491
1502
|
|
|
1492
1503
|
self.draw_screen(self.indexed_items, self.highlights)
|
|
1493
1504
|
|
|
@@ -1498,6 +1509,7 @@ class Picker:
|
|
|
1498
1509
|
self.selections[i] = False
|
|
1499
1510
|
for i in self.cell_selections.keys():
|
|
1500
1511
|
self.cell_selections[i] = False
|
|
1512
|
+
self.selected_cells_by_row = {}
|
|
1501
1513
|
self.draw_screen(self.indexed_items, self.highlights)
|
|
1502
1514
|
|
|
1503
1515
|
def handle_visual_selection(self, selecting:bool = True) -> None:
|
|
@@ -1526,9 +1538,18 @@ class Picker:
|
|
|
1526
1538
|
xend = max(self.start_selection_col, self.selected_column)
|
|
1527
1539
|
for i in range(ystart, yend + 1):
|
|
1528
1540
|
if self.indexed_items[i][0] not in self.unselectable_indices:
|
|
1529
|
-
|
|
1530
|
-
|
|
1541
|
+
row = self.indexed_items[i][0]
|
|
1542
|
+
if row not in self.selected_cells_by_row:
|
|
1543
|
+
self.selected_cells_by_row[row] = []
|
|
1544
|
+
|
|
1545
|
+
for col in range(xstart, xend+1):
|
|
1546
|
+
cell_index = (row, col)
|
|
1531
1547
|
self.cell_selections[cell_index] = True
|
|
1548
|
+
|
|
1549
|
+
self.selected_cells_by_row[row].append(col)
|
|
1550
|
+
# Remove duplicates
|
|
1551
|
+
self.selected_cells_by_row[row] = list(set(self.selected_cells_by_row[row]))
|
|
1552
|
+
|
|
1532
1553
|
self.start_selection = -1
|
|
1533
1554
|
self.end_selection = -1
|
|
1534
1555
|
self.is_selecting = False
|
|
@@ -1550,10 +1571,19 @@ class Picker:
|
|
|
1550
1571
|
xstart = min(self.start_selection_col, self.selected_column)
|
|
1551
1572
|
xend = max(self.start_selection_col, self.selected_column)
|
|
1552
1573
|
for i in range(ystart, yend + 1):
|
|
1574
|
+
row = self.indexed_items[i][0]
|
|
1553
1575
|
if self.indexed_items[i][0] not in self.unselectable_indices:
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1576
|
+
if row in self.selected_cells_by_row:
|
|
1577
|
+
for col in range(xstart, xend+1):
|
|
1578
|
+
try:
|
|
1579
|
+
self.selected_cells_by_row[row].remove(col)
|
|
1580
|
+
except:
|
|
1581
|
+
pass
|
|
1582
|
+
cell_index = (row, col)
|
|
1583
|
+
self.cell_selections[cell_index] = False
|
|
1584
|
+
if self.selected_cells_by_row[row] == []:
|
|
1585
|
+
del self.selected_cells_by_row[row]
|
|
1586
|
+
|
|
1557
1587
|
self.start_selection = -1
|
|
1558
1588
|
self.end_selection = -1
|
|
1559
1589
|
self.is_deselecting = False
|
|
@@ -1912,7 +1942,7 @@ class Picker:
|
|
|
1912
1942
|
# curses.curs_set(0)
|
|
1913
1943
|
# stdscr.nodelay(1) # Non-blocking input
|
|
1914
1944
|
# stdscr.timeout(2000) # Set a timeout for getch() to ensure it does not block indefinitely
|
|
1915
|
-
self.stdscr.timeout(max(min(2000, int(self.timer*1000)//2, int(self.footer_timer*1000))//2, 20)) # Set a timeout for getch() to ensure it does not block indefinitely
|
|
1945
|
+
# self.stdscr.timeout(max(min(2000, int(self.timer*1000)//2, int(self.footer_timer*1000))//2, 20)) # Set a timeout for getch() to ensure it does not block indefinitely
|
|
1916
1946
|
|
|
1917
1947
|
if self.clear_on_start:
|
|
1918
1948
|
self.stdscr.clear()
|
|
@@ -1929,8 +1959,6 @@ class Picker:
|
|
|
1929
1959
|
self.draw_screen(self.indexed_items, self.highlights)
|
|
1930
1960
|
|
|
1931
1961
|
if self.display_only:
|
|
1932
|
-
# self.stdscr.refresh()
|
|
1933
|
-
# function_data = self.get_function_data()
|
|
1934
1962
|
return [], "", {}
|
|
1935
1963
|
|
|
1936
1964
|
# Main loop
|
|
@@ -1958,8 +1986,8 @@ class Picker:
|
|
|
1958
1986
|
|
|
1959
1987
|
elif self.check_key("refresh", key, self.keys_dict) or self.remapped_key(key, curses.KEY_F5, self.key_remappings) or (self.auto_refresh and (time.time() - initial_time) >= self.timer):
|
|
1960
1988
|
self.logger.debug(f"Get new data (refresh).")
|
|
1961
|
-
self.stdscr.addstr(0,w-3," ", curses.color_pair(self.colours_start+21) | curses.A_BOLD)
|
|
1962
|
-
self.stdscr.refresh()
|
|
1989
|
+
# self.stdscr.addstr(0,w-3," ", curses.color_pair(self.colours_start+21) | curses.A_BOLD)
|
|
1990
|
+
# self.stdscr.refresh()
|
|
1963
1991
|
if self.get_new_data and self.refresh_function:
|
|
1964
1992
|
self.refreshing_data = True
|
|
1965
1993
|
|
|
@@ -2136,11 +2164,31 @@ class Picker:
|
|
|
2136
2164
|
if len(self.indexed_items) > 0:
|
|
2137
2165
|
item_index = self.indexed_items[self.cursor_pos][0]
|
|
2138
2166
|
cell_index = (self.indexed_items[self.cursor_pos][0], self.selected_column)
|
|
2167
|
+
row, col = cell_index
|
|
2139
2168
|
selected_count = sum(self.selections.values())
|
|
2140
2169
|
if self.max_selected == -1 or selected_count >= self.max_selected:
|
|
2141
2170
|
self.toggle_item(item_index)
|
|
2142
2171
|
|
|
2143
2172
|
self.cell_selections[cell_index] = not self.cell_selections[cell_index]
|
|
2173
|
+
# If any cells in the current row are selected
|
|
2174
|
+
if row in self.selected_cells_by_row:
|
|
2175
|
+
# If the current cell is selected then remove it
|
|
2176
|
+
if col in self.selected_cells_by_row[row]:
|
|
2177
|
+
# If the current cell is the only cell in the row that is selected then remove the row from the dict
|
|
2178
|
+
if len(self.selected_cells_by_row[row]) == 1:
|
|
2179
|
+
|
|
2180
|
+
del self.selected_cells_by_row[row]
|
|
2181
|
+
# else remove only the index of the current cell
|
|
2182
|
+
else:
|
|
2183
|
+
self.selected_cells_by_row[row].remove(col)
|
|
2184
|
+
# If there are cells in the row that are selected then append the current cell to the row
|
|
2185
|
+
else:
|
|
2186
|
+
self.selected_cells_by_row[row].append(col)
|
|
2187
|
+
# Add the a list containing only the current column
|
|
2188
|
+
else:
|
|
2189
|
+
self.selected_cells_by_row[row] = [col]
|
|
2190
|
+
|
|
2191
|
+
|
|
2144
2192
|
self.cursor_down()
|
|
2145
2193
|
elif self.check_key("select_all", key, self.keys_dict): # Select all (m or ctrl-a)
|
|
2146
2194
|
self.select_all()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|