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.
Files changed (55) hide show
  1. {listpick-0.1.13.24 → listpick-0.1.13.26}/CHANGELOG.md +1 -0
  2. {listpick-0.1.13.24/src/listpick.egg-info → listpick-0.1.13.26}/PKG-INFO +1 -1
  3. {listpick-0.1.13.24 → listpick-0.1.13.26}/setup.py +1 -1
  4. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/listpick_app.py +73 -25
  5. {listpick-0.1.13.24 → listpick-0.1.13.26/src/listpick.egg-info}/PKG-INFO +1 -1
  6. {listpick-0.1.13.24 → listpick-0.1.13.26}/.gitignore +0 -0
  7. {listpick-0.1.13.24 → listpick-0.1.13.26}/LICENSE.txt +0 -0
  8. {listpick-0.1.13.24 → listpick-0.1.13.26}/README.md +0 -0
  9. {listpick-0.1.13.24 → listpick-0.1.13.26}/TODO.md +0 -0
  10. {listpick-0.1.13.24 → listpick-0.1.13.26}/assets/aria2tui_screenshot.png +0 -0
  11. {listpick-0.1.13.24 → listpick-0.1.13.26}/assets/file_compare.png +0 -0
  12. {listpick-0.1.13.24 → listpick-0.1.13.26}/assets/lpfman.png +0 -0
  13. {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/footer_string_example.py +0 -0
  14. {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/input.toml +0 -0
  15. {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/input.txt +0 -0
  16. {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/list_files.toml +0 -0
  17. {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/list_files_empty.toml +0 -0
  18. {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/picker_example.py +0 -0
  19. {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/setup.cfg +0 -0
  20. {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/template.py +0 -0
  21. {listpick-0.1.13.24 → listpick-0.1.13.26}/examples/video_duplicates.toml +0 -0
  22. {listpick-0.1.13.24 → listpick-0.1.13.26}/listpick.py +0 -0
  23. {listpick-0.1.13.24 → listpick-0.1.13.26}/requirements.txt +0 -0
  24. {listpick-0.1.13.24 → listpick-0.1.13.26}/setup.cfg +0 -0
  25. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/__init__.py +0 -0
  26. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/__main__.py +0 -0
  27. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/__init__.py +0 -0
  28. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/build_help.py +0 -0
  29. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/footer.py +0 -0
  30. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/help_screen.py +0 -0
  31. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/input_field.py +0 -0
  32. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/keys.py +0 -0
  33. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/pane_stuff.py +0 -0
  34. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/ui/picker_colours.py +0 -0
  35. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/__init__.py +0 -0
  36. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/clipboard_operations.py +0 -0
  37. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/config.py +0 -0
  38. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/dump.py +0 -0
  39. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/filtering.py +0 -0
  40. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/generate_data.py +0 -0
  41. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/options_selectors.py +0 -0
  42. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/paste_operations.py +0 -0
  43. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/picker_log.py +0 -0
  44. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/search_and_filter_utils.py +0 -0
  45. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/searching.py +0 -0
  46. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/sorting.py +0 -0
  47. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/table_to_list_of_lists.py +0 -0
  48. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick/utils/utils.py +0 -0
  49. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick.egg-info/SOURCES.txt +0 -0
  50. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick.egg-info/dependency_links.txt +0 -0
  51. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick.egg-info/entry_points.txt +0 -0
  52. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick.egg-info/requires.txt +0 -0
  53. {listpick-0.1.13.24 → listpick-0.1.13.26}/src/listpick.egg-info/top_level.txt +0 -0
  54. {listpick-0.1.13.24 → listpick-0.1.13.26}/tests/kitty_control.sh +0 -0
  55. {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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: listpick
3
- Version: 0.1.13.24
3
+ Version: 0.1.13.26
4
4
  Summary: Listpick is a powerful TUI data tool for creating TUI apps or viewing/comparing tabulated data.
5
5
  Home-page: https://github.com/grimandgreedy/listpick
6
6
  Author: Grim
@@ -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.24",
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.infobox(self.stdscr, message=self.infobox_items, title=self.infobox_title)
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: str ="", title: str ="Infobox", colours_end: int = 0, duration: int = 4) -> curses.window:
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
- # submenu_win = curses.newwin(notification_height, notification_width, 3, w - (notification_width+4))
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
- s, o, f = OptionPicker.run()
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
- for j in range(xstart, xend+1):
1530
- cell_index = (self.indexed_items[i][0], j)
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
- for j in range(xstart, xend+1):
1555
- cell_index = (self.indexed_items[i][0], j)
1556
- self.cell_selections[cell_index] = False
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()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: listpick
3
- Version: 0.1.13.24
3
+ Version: 0.1.13.26
4
4
  Summary: Listpick is a powerful TUI data tool for creating TUI apps or viewing/comparing tabulated data.
5
5
  Home-page: https://github.com/grimandgreedy/listpick
6
6
  Author: Grim
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes