listpick 0.1.13.55__tar.gz → 0.1.13.56__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.55 → listpick-0.1.13.56}/CHANGELOG.md +0 -11
- {listpick-0.1.13.55/src/listpick.egg-info → listpick-0.1.13.56}/PKG-INFO +1 -1
- {listpick-0.1.13.55 → listpick-0.1.13.56}/TODO.md +0 -4
- {listpick-0.1.13.55 → listpick-0.1.13.56}/setup.py +1 -1
- listpick-0.1.13.55/src/listpick/lpapp2.py → listpick-0.1.13.56/src/listpick/listpick_app.py +49 -61
- listpick-0.1.13.55/src/listpick/ui/footer_1.py → listpick-0.1.13.56/src/listpick/ui/footer.py +6 -4
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/utils/utils.py +24 -50
- {listpick-0.1.13.55 → listpick-0.1.13.56/src/listpick.egg-info}/PKG-INFO +1 -1
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick.egg-info/SOURCES.txt +0 -3
- listpick-0.1.13.55/src/listpick/listpick_app.py +0 -3250
- listpick-0.1.13.55/src/listpick/listpick_app_1.py +0 -3250
- listpick-0.1.13.55/src/listpick/ui/footer.py +0 -202
- {listpick-0.1.13.55 → listpick-0.1.13.56}/.gitignore +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/LICENSE.txt +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/README.md +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/assets/aria2tui_screenshot.png +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/assets/file_compare.png +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/assets/lpfman.png +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/examples/footer_string_example.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/examples/input.toml +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/examples/input.txt +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/examples/list_files.toml +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/examples/list_files_empty.toml +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/examples/picker_example.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/examples/setup.cfg +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/examples/template.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/examples/video_duplicates.toml +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/listpick.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/requirements.txt +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/setup.cfg +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/__init__.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/__main__.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/ui/__init__.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/ui/build_help.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/ui/help_screen.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/ui/input_field.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/ui/keys.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/ui/pane_stuff.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/ui/picker_colours.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/utils/__init__.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/utils/clipboard_operations.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/utils/config.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/utils/dump.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/utils/filtering.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/utils/generate_data.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/utils/options_selectors.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/utils/paste_operations.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/utils/picker_log.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/utils/search_and_filter_utils.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/utils/searching.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/utils/sorting.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick/utils/table_to_list_of_lists.py +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick.egg-info/dependency_links.txt +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick.egg-info/entry_points.txt +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick.egg-info/requires.txt +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/src/listpick.egg-info/top_level.txt +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/tests/kitty_control.sh +0 -0
- {listpick-0.1.13.55 → listpick-0.1.13.56}/tests/sorting_dates.csv +0 -0
|
@@ -25,17 +25,6 @@
|
|
|
25
25
|
- Setup logging for the Picker class. Currently still very basic but will track to the last function that was run before crash if the --debug flag is passed to the picker.
|
|
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
|
-
- Reduced 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.
|
|
30
|
-
- Added unicode_char_width option which will set the calculating character widths. If True then wcwidth will be used to calculate the display with if False then len will be used.
|
|
31
|
-
- unicode_char_width should be set to true if special characters will be displayed
|
|
32
|
-
- Special characters=East Asian scripts, emojis, etc.
|
|
33
|
-
- With data that has several thousand columns wcwidth is extremely slow so unicode_char_width should be set to False.
|
|
34
|
-
- Speed improvements:
|
|
35
|
-
- get_column_widths calculated only once when drawing the screen.
|
|
36
|
-
- unicode_char_width option to improve performance with large (in particular wide) data sets.
|
|
37
|
-
- truncate_to_display width now guesses the target width and then adjusts rather than adding one display-width character at a time. 5-10 times faster.
|
|
38
|
-
- Reduced number of calls to draw_screen. It is called (1) when a key is pressed, (2) before showing a notification, and (3) when the data is refreshed.
|
|
39
28
|
|
|
40
29
|
## [0.1.13] 2025-07-28
|
|
41
30
|
- Cell-based picker is now supported.
|
|
@@ -5,9 +5,6 @@ ASAP
|
|
|
5
5
|
> - [ ] Unify in-app load and command-line input file
|
|
6
6
|
> - [ ] Implement default_option_selector and pass the picker options (!!!)
|
|
7
7
|
> - [ ] Make sure that all class initialisation variables are returned in the get_function_variables function.
|
|
8
|
-
> - [ ] Adjust leftmost_char when:
|
|
9
|
-
> - [ ] cursor_down
|
|
10
|
-
> - [ ] 'g', 'G'
|
|
11
8
|
|
|
12
9
|
|
|
13
10
|
|
|
@@ -117,7 +114,6 @@ ASAP
|
|
|
117
114
|
> - [x] Support pasting copied cells into the picker
|
|
118
115
|
> - [ ] Ensure that we can only paste when cells are editable.
|
|
119
116
|
> - [ ] Add option to insert cells; e.g., insert two columns and move the data to the right of the selected column across
|
|
120
|
-
> - [ ] Add support for pasting as a string
|
|
121
117
|
> - [ ] Support inserting cells/rows.
|
|
122
118
|
> - [ ] Bulk edit in nvim
|
|
123
119
|
> - [ ] Add formula and display value...
|
|
@@ -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.56",
|
|
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.",
|
|
@@ -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,6 +312,8 @@ 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
|
|
|
@@ -323,7 +324,6 @@ class Picker:
|
|
|
323
324
|
# self.footer = CompactFooter(self.stdscr, colours_start, self.get_function_data)
|
|
324
325
|
|
|
325
326
|
|
|
326
|
-
|
|
327
327
|
def calculate_section_sizes(self):
|
|
328
328
|
"""
|
|
329
329
|
Calculte the following for the Picker:
|
|
@@ -384,6 +384,7 @@ class Picker:
|
|
|
384
384
|
def initialise_picker_state(self, reset_colours=False) -> None:
|
|
385
385
|
""" Initialise state variables for the picker. These are: debugging and colours. """
|
|
386
386
|
|
|
387
|
+
|
|
387
388
|
if curses.has_colors() and self.colours != None:
|
|
388
389
|
# raise Exception("Terminal does not support color")
|
|
389
390
|
curses.start_color()
|
|
@@ -473,6 +474,7 @@ class Picker:
|
|
|
473
474
|
|
|
474
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:
|
|
475
476
|
self.cursor_pos_id = self.indexed_items[self.cursor_pos][1][self.id_column]
|
|
477
|
+
self.cursor_pos_prev = self.cursor_pos
|
|
476
478
|
|
|
477
479
|
self.items, self.header = self.refresh_function()
|
|
478
480
|
|
|
@@ -679,12 +681,12 @@ class Picker:
|
|
|
679
681
|
end_index = min(start_index + self.items_per_page, len(self.indexed_items))
|
|
680
682
|
if len(self.indexed_items) == 0: start_index, end_index = 0, 0
|
|
681
683
|
|
|
682
|
-
# self.column_widths = get_column_widths(self.items, header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns)
|
|
684
|
+
# 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)
|
|
683
685
|
# Determine widths based only on the currently indexed rows
|
|
684
686
|
# rows = [v[1] for v in self.indexed_items] if len(self.indexed_items) else self.items
|
|
685
687
|
# Determine widths based only on the currently displayed indexed rows
|
|
686
688
|
rows = [v[1] for v in self.indexed_items[start_index:end_index]] if len(self.indexed_items) else self.items
|
|
687
|
-
self.column_widths = get_column_widths(rows, header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns)
|
|
689
|
+
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)
|
|
688
690
|
visible_column_widths = [c for i,c in enumerate(self.column_widths) if i not in self.hidden_columns]
|
|
689
691
|
visible_columns_total_width = sum(visible_column_widths) + len(self.separator)*(len(visible_column_widths)-1)
|
|
690
692
|
|
|
@@ -982,7 +984,6 @@ class Picker:
|
|
|
982
984
|
disp_string = f" {self.footer_string[:footer_string_width]:>{footer_string_width-2}} "
|
|
983
985
|
self.stdscr.addstr(h - 1, w-footer_string_width-1, " "*footer_string_width, curses.color_pair(self.colours_start+24))
|
|
984
986
|
self.stdscr.addstr(h - 1, w-footer_string_width-1, f"{disp_string}", curses.color_pair(self.colours_start+24))
|
|
985
|
-
self.stdscr.refresh()
|
|
986
987
|
|
|
987
988
|
## Display infobox
|
|
988
989
|
if self.display_infobox:
|
|
@@ -1131,7 +1132,6 @@ class Picker:
|
|
|
1131
1132
|
"debug": self.debug,
|
|
1132
1133
|
"debug_level": self.debug_level,
|
|
1133
1134
|
"reset_colours": self.reset_colours,
|
|
1134
|
-
"unicode_char_width": self.unicode_char_width,
|
|
1135
1135
|
}
|
|
1136
1136
|
return function_data
|
|
1137
1137
|
|
|
@@ -1385,8 +1385,6 @@ class Picker:
|
|
|
1385
1385
|
self.initialise_variables()
|
|
1386
1386
|
elif setting == "pc":
|
|
1387
1387
|
self.pin_cursor = not self.pin_cursor
|
|
1388
|
-
elif setting == "unicode":
|
|
1389
|
-
self.unicode_char_width = not self.unicode_char_width
|
|
1390
1388
|
|
|
1391
1389
|
elif setting.startswith("ft"):
|
|
1392
1390
|
if len(setting) > 2 and setting[2:].isnumeric():
|
|
@@ -1450,6 +1448,7 @@ class Picker:
|
|
|
1450
1448
|
self.draw_screen(self.indexed_items, self.highlights)
|
|
1451
1449
|
self.notification(self.stdscr, message=f"Theme {self.colour_theme_number} applied.")
|
|
1452
1450
|
|
|
1451
|
+
|
|
1453
1452
|
else:
|
|
1454
1453
|
self.user_settings = ""
|
|
1455
1454
|
return None
|
|
@@ -1520,18 +1519,9 @@ class Picker:
|
|
|
1520
1519
|
xend = max(self.start_selection_col, self.selected_column)
|
|
1521
1520
|
for i in range(ystart, yend + 1):
|
|
1522
1521
|
if self.indexed_items[i][0] not in self.unselectable_indices:
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
self.selected_cells_by_row[row] = []
|
|
1526
|
-
|
|
1527
|
-
for col in range(xstart, xend+1):
|
|
1528
|
-
cell_index = (row, col)
|
|
1522
|
+
for j in range(xstart, xend+1):
|
|
1523
|
+
cell_index = (self.indexed_items[i][0], j)
|
|
1529
1524
|
self.cell_selections[cell_index] = True
|
|
1530
|
-
|
|
1531
|
-
self.selected_cells_by_row[row].append(col)
|
|
1532
|
-
# Remove duplicates
|
|
1533
|
-
self.selected_cells_by_row[row] = list(set(self.selected_cells_by_row[row]))
|
|
1534
|
-
|
|
1535
1525
|
self.start_selection = -1
|
|
1536
1526
|
self.end_selection = -1
|
|
1537
1527
|
self.is_selecting = False
|
|
@@ -1565,6 +1555,8 @@ class Picker:
|
|
|
1565
1555
|
def cursor_down(self, count=1) -> bool:
|
|
1566
1556
|
""" Move cursor down. """
|
|
1567
1557
|
self.logger.info(f"function: cursor_down()")
|
|
1558
|
+
if len(self.indexed_items) == 0 or self.cursor_pos == len(self.indexed_items) -1:
|
|
1559
|
+
return False
|
|
1568
1560
|
# Returns: whether page is turned
|
|
1569
1561
|
new_pos = self.cursor_pos + 1
|
|
1570
1562
|
new_pos = min(self.cursor_pos+count, len(self.indexed_items)-1)
|
|
@@ -1783,6 +1775,7 @@ class Picker:
|
|
|
1783
1775
|
|
|
1784
1776
|
if len(self.indexed_items) > 0 and len(self.indexed_items) >= self.cursor_pos and len(self.indexed_items[0][1]) >= self.id_column:
|
|
1785
1777
|
self.cursor_pos_id = self.indexed_items[self.cursor_pos][1][self.id_column]
|
|
1778
|
+
self.cursor_pos_prev = self.cursor_pos
|
|
1786
1779
|
with self.data_lock:
|
|
1787
1780
|
self.items, self.header = tmp_items, tmp_header
|
|
1788
1781
|
self.data_ready = True
|
|
@@ -1832,7 +1825,7 @@ class Picker:
|
|
|
1832
1825
|
|
|
1833
1826
|
def get_word_list(self) -> list[str]:
|
|
1834
1827
|
""" Get a list of all words used in any cell of the picker. Used for completion in search/filter input_field. """
|
|
1835
|
-
self.logger.info(f"function:
|
|
1828
|
+
self.logger.info(f"function: infobox()")
|
|
1836
1829
|
translator = str.maketrans('', '', string.punctuation)
|
|
1837
1830
|
|
|
1838
1831
|
words = []
|
|
@@ -1940,6 +1933,7 @@ class Picker:
|
|
|
1940
1933
|
|
|
1941
1934
|
while True:
|
|
1942
1935
|
key = self.stdscr.getch()
|
|
1936
|
+
h, w = self.stdscr.getmaxyx()
|
|
1943
1937
|
if key in self.disabled_keys: continue
|
|
1944
1938
|
clear_screen=True
|
|
1945
1939
|
|
|
@@ -1960,7 +1954,6 @@ class Picker:
|
|
|
1960
1954
|
|
|
1961
1955
|
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):
|
|
1962
1956
|
self.logger.debug(f"Get new data (refresh).")
|
|
1963
|
-
h, w = self.stdscr.getmaxyx()
|
|
1964
1957
|
self.stdscr.addstr(0,w-3," ", curses.color_pair(self.colours_start+21) | curses.A_BOLD)
|
|
1965
1958
|
self.stdscr.refresh()
|
|
1966
1959
|
if self.get_new_data and self.refresh_function:
|
|
@@ -1974,7 +1967,6 @@ class Picker:
|
|
|
1974
1967
|
|
|
1975
1968
|
# Refresh data synchronously
|
|
1976
1969
|
# if 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):
|
|
1977
|
-
# h, w = self.stdscr.getmaxyx()
|
|
1978
1970
|
# self.stdscr.addstr(0,w-3," ", curses.color_pair(self.colours_start+21) | curses.A_BOLD)
|
|
1979
1971
|
# self.stdscr.refresh()
|
|
1980
1972
|
# if self.get_new_data and self.refresh_function:
|
|
@@ -2076,7 +2068,6 @@ class Picker:
|
|
|
2076
2068
|
options += [["rh", "Toggle row header"]]
|
|
2077
2069
|
options += [["modes", "Toggle modes"]]
|
|
2078
2070
|
options += [["ft", "Cycle through footer styles (accepts ft#)"]]
|
|
2079
|
-
options += [["unicode", "Toggle b/w using len and wcwidth to calculate char width."]]
|
|
2080
2071
|
options += [[f"s{i}", f"Select col. {i}"] for i in range(len(self.items[0]))]
|
|
2081
2072
|
options += [[f"!{i}", f"Toggle col. {i}"] for i in range(len(self.items[0]))]
|
|
2082
2073
|
options += [["ara", "Add empty row after cursor."]]
|
|
@@ -2102,7 +2093,7 @@ class Picker:
|
|
|
2102
2093
|
# self.selected_column = (self.selected_column-1)%len(self.column_indices)
|
|
2103
2094
|
# # self.notification(self.stdscr, f"{str(self.column_indices)}, {tmp1}, {tmp2}")
|
|
2104
2095
|
# self.initialise_variables()
|
|
2105
|
-
# self.column_widths = get_column_widths([v[1] for v in self.indexed_items], header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns)
|
|
2096
|
+
# self.column_widths = get_column_widths([v[1] for v in self.indexed_items], header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns, max_total_width=w)
|
|
2106
2097
|
# self.draw_screen(self.indexed_items, self.highlights)
|
|
2107
2098
|
# # self.move_column(direction=-1)
|
|
2108
2099
|
#
|
|
@@ -2120,19 +2111,22 @@ class Picker:
|
|
|
2120
2111
|
page_turned = self.cursor_down()
|
|
2121
2112
|
if not page_turned: clear_screen = False
|
|
2122
2113
|
elif self.check_key("half_page_down", key, self.keys_dict):
|
|
2123
|
-
clear_screen = False
|
|
2124
2114
|
self.cursor_down(count=self.items_per_page//2)
|
|
2115
|
+
clear_screen = True
|
|
2125
2116
|
elif self.check_key("five_down", key, self.keys_dict):
|
|
2126
2117
|
clear_screen = False
|
|
2127
2118
|
self.cursor_down(count=5)
|
|
2119
|
+
clear_screen = True
|
|
2128
2120
|
elif self.check_key("cursor_up", key, self.keys_dict):
|
|
2129
2121
|
page_turned = self.cursor_up()
|
|
2130
2122
|
if not page_turned: clear_screen = False
|
|
2131
2123
|
elif self.check_key("five_up", key, self.keys_dict):
|
|
2132
2124
|
# if self.cursor_up(count=5): clear_screen = True
|
|
2133
2125
|
self.cursor_up(count=5)
|
|
2126
|
+
clear_screen = True
|
|
2134
2127
|
elif self.check_key("half_page_up", key, self.keys_dict):
|
|
2135
2128
|
self.cursor_up(count=self.items_per_page//2)
|
|
2129
|
+
clear_screen = True
|
|
2136
2130
|
|
|
2137
2131
|
elif self.check_key("toggle_select", key, self.keys_dict):
|
|
2138
2132
|
if len(self.indexed_items) > 0:
|
|
@@ -2143,25 +2137,6 @@ class Picker:
|
|
|
2143
2137
|
self.toggle_item(item_index)
|
|
2144
2138
|
|
|
2145
2139
|
self.cell_selections[cell_index] = not self.cell_selections[cell_index]
|
|
2146
|
-
## Set self.selected_cells_by_row
|
|
2147
|
-
# If any cells in the current row are selected
|
|
2148
|
-
if row in self.selected_cells_by_row:
|
|
2149
|
-
# If the current cell is selected then remove it
|
|
2150
|
-
if col in self.selected_cells_by_row[row]:
|
|
2151
|
-
# If the current cell is the only cell in the row that is selected then remove the row from the dict
|
|
2152
|
-
if len(self.selected_cells_by_row[row]) == 1:
|
|
2153
|
-
|
|
2154
|
-
del self.selected_cells_by_row[row]
|
|
2155
|
-
# else remove only the index of the current cell
|
|
2156
|
-
else:
|
|
2157
|
-
self.selected_cells_by_row[row].remove(col)
|
|
2158
|
-
# If there are cells in the row that are selected then append the current cell to the row
|
|
2159
|
-
else:
|
|
2160
|
-
self.selected_cells_by_row[row].append(col)
|
|
2161
|
-
# Add the a list containing only the current column
|
|
2162
|
-
else:
|
|
2163
|
-
self.selected_cells_by_row[row] = [col]
|
|
2164
|
-
|
|
2165
2140
|
self.cursor_down()
|
|
2166
2141
|
elif self.check_key("select_all", key, self.keys_dict): # Select all (m or ctrl-a)
|
|
2167
2142
|
self.select_all()
|
|
@@ -2186,7 +2161,12 @@ class Picker:
|
|
|
2186
2161
|
else: break
|
|
2187
2162
|
if new_pos < len(self.items) and new_pos >= 0:
|
|
2188
2163
|
self.cursor_pos = new_pos
|
|
2189
|
-
|
|
2164
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
2165
|
+
# current_row = items_per_page - 1
|
|
2166
|
+
# if current_page + 1 == (len(self.indexed_items) + items_per_page - 1) // items_per_page:
|
|
2167
|
+
#
|
|
2168
|
+
# current_row = (len(self.indexed_items) +items_per_page - 1) % items_per_page
|
|
2169
|
+
# self.draw_screen(self.indexed_items, self.highlights)
|
|
2190
2170
|
elif self.check_key("enter", key, self.keys_dict):
|
|
2191
2171
|
self.logger.info(f"key_function enter")
|
|
2192
2172
|
# Print the selected indices if any, otherwise print the current index
|
|
@@ -2266,6 +2246,7 @@ class Picker:
|
|
|
2266
2246
|
if len(self.indexed_items) > 0:
|
|
2267
2247
|
current_index = self.indexed_items[self.cursor_pos][0]
|
|
2268
2248
|
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
|
|
2249
|
+
self.draw_screen(self.indexed_items, self.highlights)
|
|
2269
2250
|
self.cursor_pos = [row[0] for row in self.indexed_items].index(current_index)
|
|
2270
2251
|
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]})")
|
|
2271
2252
|
elif self.check_key("col_select", key, self.keys_dict):
|
|
@@ -2289,10 +2270,10 @@ class Picker:
|
|
|
2289
2270
|
|
|
2290
2271
|
## Scroll with column select
|
|
2291
2272
|
rows = self.get_visible_rows()
|
|
2292
|
-
self.column_widths = get_column_widths(rows, header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns)
|
|
2273
|
+
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)
|
|
2293
2274
|
visible_column_widths = [c for i,c in enumerate(self.column_widths) if i not in self.hidden_columns]
|
|
2294
|
-
|
|
2295
|
-
|
|
2275
|
+
column_set_width = sum(visible_column_widths)+len(self.separator)*len(visible_column_widths)
|
|
2276
|
+
start_of_cell = sum(visible_column_widths[:self.selected_column])+len(self.separator)*self.selected_column
|
|
2296
2277
|
end_of_cell = sum(visible_column_widths[:self.selected_column+1])+len(self.separator)*(self.selected_column+1)
|
|
2297
2278
|
display_width = w-self.startx
|
|
2298
2279
|
# If the full column is within the current display then don't do anything
|
|
@@ -2316,7 +2297,8 @@ class Picker:
|
|
|
2316
2297
|
|
|
2317
2298
|
## Scroll with column select
|
|
2318
2299
|
rows = self.get_visible_rows()
|
|
2319
|
-
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
|
|
2300
|
+
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)
|
|
2301
|
+
|
|
2320
2302
|
visible_column_widths = [c for i,c in enumerate(self.column_widths) if i not in self.hidden_columns]
|
|
2321
2303
|
column_set_width = sum(visible_column_widths)+len(self.separator)*len(visible_column_widths)
|
|
2322
2304
|
start_of_cell = sum(visible_column_widths[:self.selected_column])+len(self.separator)*self.selected_column
|
|
@@ -2331,13 +2313,18 @@ class Picker:
|
|
|
2331
2313
|
self.leftmost_char = start_of_cell
|
|
2332
2314
|
|
|
2333
2315
|
self.leftmost_char = max(0, min(column_set_width - display_width + 5, self.leftmost_char))
|
|
2334
|
-
|
|
2316
|
+
#
|
|
2335
2317
|
elif self.check_key("scroll_right", key, self.keys_dict):
|
|
2336
2318
|
self.logger.info(f"key_function scroll_right")
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2319
|
+
rows = self.get_visible_rows()
|
|
2320
|
+
longest_row_str_len = 0
|
|
2321
|
+
for i in range(len(rows)):
|
|
2322
|
+
item = rows[i]
|
|
2323
|
+
row_str = format_row(item, self.hidden_columns, self.column_widths, self.separator, self.centre_in_cols)[self.leftmost_char:]
|
|
2324
|
+
if len(row_str) > longest_row_str_len: longest_row_str_len=len(row_str)
|
|
2325
|
+
|
|
2326
|
+
if longest_row_str_len >= w-self.startx:
|
|
2327
|
+
self.leftmost_char = self.leftmost_char+5
|
|
2341
2328
|
|
|
2342
2329
|
elif self.check_key("scroll_left", key, self.keys_dict):
|
|
2343
2330
|
self.logger.info(f"key_function scroll_left")
|
|
@@ -2434,13 +2421,13 @@ class Picker:
|
|
|
2434
2421
|
self.logger.info(f"key_function decrease_column_width")
|
|
2435
2422
|
if self.max_column_width > 10:
|
|
2436
2423
|
self.max_column_width -= 10
|
|
2437
|
-
self.column_widths
|
|
2424
|
+
# 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)
|
|
2438
2425
|
self.draw_screen(self.indexed_items, self.highlights)
|
|
2439
2426
|
elif self.check_key("increase_column_width", key, self.keys_dict):
|
|
2440
2427
|
self.logger.info(f"key_function increase_column_width")
|
|
2441
2428
|
if self.max_column_width < 1000:
|
|
2442
2429
|
self.max_column_width += 10
|
|
2443
|
-
self.column_widths = get_column_widths(self.items, header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns)
|
|
2430
|
+
# 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)
|
|
2444
2431
|
self.draw_screen(self.indexed_items, self.highlights)
|
|
2445
2432
|
elif self.check_key("visual_selection_toggle", key, self.keys_dict):
|
|
2446
2433
|
self.logger.info(f"key_function visual_selection_toggle")
|
|
@@ -2455,7 +2442,7 @@ class Picker:
|
|
|
2455
2442
|
elif key == curses.KEY_RESIZE: # Terminal resize signal
|
|
2456
2443
|
|
|
2457
2444
|
self.calculate_section_sizes()
|
|
2458
|
-
self.column_widths = get_column_widths(self.items, header=self.header, max_column_width=self.max_column_width, number_columns=self.number_columns)
|
|
2445
|
+
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)
|
|
2459
2446
|
|
|
2460
2447
|
self.draw_screen(self.indexed_items, self.highlights)
|
|
2461
2448
|
|
|
@@ -2982,7 +2969,7 @@ def set_colours(pick: int = 0, start: int = 0) -> Optional[int]:
|
|
|
2982
2969
|
def parse_arguments() -> Tuple[argparse.Namespace, dict]:
|
|
2983
2970
|
""" Parse command line arguments. """
|
|
2984
2971
|
parser = argparse.ArgumentParser(description='Convert table to list of lists.')
|
|
2985
|
-
parser.add_argument('filename', type=str, help='The file to process')
|
|
2972
|
+
# parser.add_argument('filename', type=str, help='The file to process')
|
|
2986
2973
|
parser.add_argument('-i', dest='file', help='File containing the table to be converted.')
|
|
2987
2974
|
parser.add_argument('--load', '-l', dest='load', type=str, help='Load file from Picker dump.')
|
|
2988
2975
|
parser.add_argument('--stdin', dest='stdin', action='store_true', help='Table passed on stdin')
|
|
@@ -3010,8 +2997,8 @@ def parse_arguments() -> Tuple[argparse.Namespace, dict]:
|
|
|
3010
2997
|
input_arg = '--stdin'
|
|
3011
2998
|
elif args.stdin2:
|
|
3012
2999
|
input_arg = '--stdin2'
|
|
3013
|
-
elif args.filename:
|
|
3014
|
-
|
|
3000
|
+
# elif args.filename:
|
|
3001
|
+
# input_arg = args.filename
|
|
3015
3002
|
|
|
3016
3003
|
elif args.generate:
|
|
3017
3004
|
function_data["refresh_function"] = lambda : generate_picker_data(args.generate)
|
|
@@ -3122,6 +3109,7 @@ def main() -> None:
|
|
|
3122
3109
|
function_data["track_entries_upon_refresh"] = True
|
|
3123
3110
|
function_data["centre_in_terminal_vertical"] = True
|
|
3124
3111
|
function_data["highlight_full_row"] = True
|
|
3112
|
+
function_data["pin_cursor"] = True
|
|
3125
3113
|
# function_data["debug"] = True
|
|
3126
3114
|
# function_data["debug_level"] = 1
|
|
3127
3115
|
stdscr = start_curses()
|
listpick-0.1.13.55/src/listpick/ui/footer_1.py → listpick-0.1.13.56/src/listpick/ui/footer.py
RENAMED
|
@@ -50,9 +50,6 @@ class StandardFooter(Footer):
|
|
|
50
50
|
def draw(self, h, w):
|
|
51
51
|
state = self.get_state()
|
|
52
52
|
# Fill background
|
|
53
|
-
if "footer_string" in state and state["footer_string"]: self.height = 3
|
|
54
|
-
else: self.height = 2
|
|
55
|
-
|
|
56
53
|
for i in range(self.height):
|
|
57
54
|
self.stdscr.addstr(h-self.height+i, 0, ' '*(w-1), curses.color_pair(self.colours_start+20))
|
|
58
55
|
|
|
@@ -66,14 +63,19 @@ class StandardFooter(Footer):
|
|
|
66
63
|
|
|
67
64
|
picker_info_y = h-3
|
|
68
65
|
sort_info_y = h-2
|
|
66
|
+
self.height = 3
|
|
67
|
+
|
|
69
68
|
else:
|
|
70
69
|
picker_info_y = h-2
|
|
71
70
|
sort_info_y = h-1
|
|
71
|
+
""
|
|
72
72
|
select_mode = "C"
|
|
73
73
|
if state["is_selecting"]: select_mode = "VS"
|
|
74
74
|
elif state["is_deselecting"]: select_mode = "VDS"
|
|
75
75
|
if state["pin_cursor"]: select_mode = f"{select_mode} "
|
|
76
76
|
self.stdscr.addstr(h - 1, w-35, f"{select_mode:>33} ", curses.color_pair(self.colours_start+20))
|
|
77
|
+
self.height = 2
|
|
78
|
+
|
|
77
79
|
|
|
78
80
|
if state["filter_query"]:
|
|
79
81
|
self.stdscr.addstr(h - 2, 2, f" Filter: {state['filter_query']} "[:w-40], curses.color_pair(self.colours_start+20) | curses.A_BOLD)
|
|
@@ -105,7 +107,7 @@ class StandardFooter(Footer):
|
|
|
105
107
|
sort_disp_str = f" Sort: ({sort_column_info}, {sort_method_info}, {sort_order_info}) "
|
|
106
108
|
self.stdscr.addstr(sort_info_y, w-35, f"{sort_disp_str:>34}", curses.color_pair(self.colours_start+20))
|
|
107
109
|
|
|
108
|
-
|
|
110
|
+
self.stdscr.refresh()
|
|
109
111
|
|
|
110
112
|
|
|
111
113
|
|
|
@@ -36,7 +36,7 @@ def clip_left(text, n):
|
|
|
36
36
|
width += char_width
|
|
37
37
|
return text # If the total width is less than n, return the full string
|
|
38
38
|
|
|
39
|
-
def truncate_to_display_width(text: str, max_column_width: int, centre=False
|
|
39
|
+
def truncate_to_display_width(text: str, max_column_width: int, centre=False) -> str:
|
|
40
40
|
"""
|
|
41
41
|
Truncate and/or pad text to max_column_width using wcwidth to ensure visual width is correct
|
|
42
42
|
with foreign character sets.
|
|
@@ -46,36 +46,19 @@ def truncate_to_display_width(text: str, max_column_width: int, centre=False, un
|
|
|
46
46
|
|
|
47
47
|
"""
|
|
48
48
|
# logger.debug("function: truncate_to_display_width (utils.py)")
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
# test_str = text[:max_column_width]
|
|
64
|
-
# while True:
|
|
65
|
-
# width = wcswidth(test_str)
|
|
66
|
-
# if width < max_column_width or width == 0:
|
|
67
|
-
# break
|
|
68
|
-
# test_str = test_str[:-1]
|
|
69
|
-
# result = test_str
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
# Pad if it's shorter
|
|
73
|
-
# padding = max_column_width - wcswidth(result)
|
|
74
|
-
# return result + ' ' * padding
|
|
75
|
-
else:
|
|
76
|
-
result = text[:max_column_width]
|
|
77
|
-
width = len(result)
|
|
78
|
-
padding = max_column_width - width
|
|
49
|
+
result = ''
|
|
50
|
+
width = 0
|
|
51
|
+
for char in text:
|
|
52
|
+
w = wcwidth(char)
|
|
53
|
+
if w < 0:
|
|
54
|
+
continue
|
|
55
|
+
if width + w > max_column_width:
|
|
56
|
+
break
|
|
57
|
+
result += char
|
|
58
|
+
width += w
|
|
59
|
+
# Pad if it's shorter
|
|
60
|
+
padding = max_column_width - wcswidth(result)
|
|
61
|
+
# return result + ' ' * padding
|
|
79
62
|
if centre:
|
|
80
63
|
result = ' '*(padding//2) + result + ' '*(padding//2 + padding%2)
|
|
81
64
|
else:
|
|
@@ -100,7 +83,7 @@ def format_full_row(row:str) -> str:
|
|
|
100
83
|
return '\t'.join(row)
|
|
101
84
|
|
|
102
85
|
|
|
103
|
-
def format_row(row: list[str], hidden_columns: list, column_widths: list[int], separator: str, centre:bool=False
|
|
86
|
+
def format_row(row: list[str], hidden_columns: list, column_widths: list[int], separator: str, centre:bool=False) -> str:
|
|
104
87
|
""" Format list of strings as a single string. Requires separator string and the maximum width of the columns. """
|
|
105
88
|
row_str = ""
|
|
106
89
|
for i, cell in enumerate(row):
|
|
@@ -108,22 +91,20 @@ def format_row(row: list[str], hidden_columns: list, column_widths: list[int], s
|
|
|
108
91
|
# if is_formula_cell(cell):
|
|
109
92
|
# cell = evaluate_cell(cell)
|
|
110
93
|
|
|
111
|
-
val = truncate_to_display_width(str(cell), column_widths[i], centre
|
|
94
|
+
val = truncate_to_display_width(str(cell), column_widths[i], centre)
|
|
112
95
|
row_str += val + separator
|
|
113
96
|
return row_str
|
|
97
|
+
# return row_str.strip()
|
|
114
98
|
|
|
115
|
-
def get_column_widths(items: list[list[str]], header: list[str]=[], max_column_width:int=70, number_columns:bool=True, max_total_width=-1, separator = " "
|
|
99
|
+
def get_column_widths(items: list[list[str]], header: list[str]=[], max_column_width:int=70, number_columns:bool=True, max_total_width=-1, separator = " ") -> list[int]:
|
|
116
100
|
""" Calculate maximum width of each column with clipping. """
|
|
117
101
|
if len(items) == 0: return [0]
|
|
118
102
|
assert len(items) > 0
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
header_widths = [wcswidth(f"{i}. {str(h)}") if number_columns else wcswidth(str(h)) for i, h in enumerate(header)]
|
|
125
|
-
col_widths = [min(max_column_width, max(widths[i], header_widths[i])) for i in range(len(header))]
|
|
126
|
-
|
|
103
|
+
widths = [max(wcswidth(str(row[i])) for row in items) for i in range(len(items[0]))]
|
|
104
|
+
# widths = [max(len(str(row[i])) for row in items) for i in range(len(items[0]))]
|
|
105
|
+
if header:
|
|
106
|
+
header_widths = [wcswidth(f"{i}. {str(h)}") if number_columns else wcswidth(str(h)) for i, h in enumerate(header)]
|
|
107
|
+
col_widths = [min(max_column_width, max(widths[i], header_widths[i])) for i in range(len(header))]
|
|
127
108
|
# actual_max_widths = [max(header_widths[i], widths[i]) for i in range(len(widths))]
|
|
128
109
|
#
|
|
129
110
|
# if sum(col_widths) + len(separator)*(len(col_widths)-1) < max_total_width:
|
|
@@ -143,15 +124,8 @@ def get_column_widths(items: list[list[str]], header: list[str]=[], max_column_w
|
|
|
143
124
|
# else:
|
|
144
125
|
# # Maximise balance.....
|
|
145
126
|
# pass
|
|
146
|
-
else:
|
|
147
|
-
col_widths = [min(max_column_width, width) for width in widths]
|
|
148
127
|
else:
|
|
149
|
-
|
|
150
|
-
if header:
|
|
151
|
-
header_widths = [len(f"{i}. {str(h)}") if number_columns else len(str(h)) for i, h in enumerate(header)]
|
|
152
|
-
col_widths = [min(max_column_width, max(widths[i], header_widths[i])) for i in range(len(header))]
|
|
153
|
-
else:
|
|
154
|
-
col_widths = [min(max_column_width, width) for width in widths]
|
|
128
|
+
col_widths = [min(max_column_width, width) for width in widths]
|
|
155
129
|
return col_widths
|
|
156
130
|
|
|
157
131
|
def get_mode_widths(item_list: list[str]) -> list[int]:
|
|
@@ -21,8 +21,6 @@ examples/video_duplicates.toml
|
|
|
21
21
|
src/listpick/__init__.py
|
|
22
22
|
src/listpick/__main__.py
|
|
23
23
|
src/listpick/listpick_app.py
|
|
24
|
-
src/listpick/listpick_app_1.py
|
|
25
|
-
src/listpick/lpapp2.py
|
|
26
24
|
src/listpick.egg-info/PKG-INFO
|
|
27
25
|
src/listpick.egg-info/SOURCES.txt
|
|
28
26
|
src/listpick.egg-info/dependency_links.txt
|
|
@@ -32,7 +30,6 @@ src/listpick.egg-info/top_level.txt
|
|
|
32
30
|
src/listpick/ui/__init__.py
|
|
33
31
|
src/listpick/ui/build_help.py
|
|
34
32
|
src/listpick/ui/footer.py
|
|
35
|
-
src/listpick/ui/footer_1.py
|
|
36
33
|
src/listpick/ui/help_screen.py
|
|
37
34
|
src/listpick/ui/input_field.py
|
|
38
35
|
src/listpick/ui/keys.py
|