listpick 0.1.13.59__py3-none-any.whl → 0.1.13.61__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of listpick might be problematic. Click here for more details.
- listpick/listpick_app.py +3 -2
- listpick/utils/utils.py +17 -0
- {listpick-0.1.13.59.dist-info → listpick-0.1.13.61.dist-info}/METADATA +1 -1
- {listpick-0.1.13.59.dist-info → listpick-0.1.13.61.dist-info}/RECORD +8 -9
- listpick/ui/footer_1.py +0 -202
- {listpick-0.1.13.59.dist-info → listpick-0.1.13.61.dist-info}/WHEEL +0 -0
- {listpick-0.1.13.59.dist-info → listpick-0.1.13.61.dist-info}/entry_points.txt +0 -0
- {listpick-0.1.13.59.dist-info → listpick-0.1.13.61.dist-info}/licenses/LICENSE.txt +0 -0
- {listpick-0.1.13.59.dist-info → listpick-0.1.13.61.dist-info}/top_level.txt +0 -0
listpick/listpick_app.py
CHANGED
|
@@ -449,8 +449,6 @@ class Picker:
|
|
|
449
449
|
# self.stdscr.refresh()
|
|
450
450
|
# self.draw_screen(self.indexed_items, self.highlights)
|
|
451
451
|
|
|
452
|
-
|
|
453
|
-
|
|
454
452
|
def initialise_variables(self, get_data: bool = False) -> None:
|
|
455
453
|
""" Initialise the variables that keep track of the data. """
|
|
456
454
|
|
|
@@ -473,6 +471,7 @@ class Picker:
|
|
|
473
471
|
|
|
474
472
|
self.items, self.header = self.refresh_function()
|
|
475
473
|
|
|
474
|
+
self.items = pad_lists_to_same_length(self.items)
|
|
476
475
|
|
|
477
476
|
if self.items == []: self.items = [[]]
|
|
478
477
|
## Ensure that items is a List[List[Str]] object
|
|
@@ -1959,6 +1958,8 @@ class Picker:
|
|
|
1959
1958
|
|
|
1960
1959
|
while True:
|
|
1961
1960
|
key = self.stdscr.getch()
|
|
1961
|
+
if key:
|
|
1962
|
+
self.logger.info(f"key={key}")
|
|
1962
1963
|
h, w = self.stdscr.getmaxyx()
|
|
1963
1964
|
if key in self.disabled_keys: continue
|
|
1964
1965
|
clear_screen=True
|
listpick/utils/utils.py
CHANGED
|
@@ -344,3 +344,20 @@ def guess_file_type(filename: str) -> str:
|
|
|
344
344
|
""" Guess filetype. Currently just uses the extension of the file. """
|
|
345
345
|
logger.info("function: guess_file_type (utils.py)")
|
|
346
346
|
return filename.split(".")[-1]
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def pad_lists_to_same_length(list_of_lists: list[list[str]]) -> list[list[str]]:
|
|
350
|
+
""" Ensure that all lists in a list of lists are of the same length. Pad any shorter sublists with empty strings. """
|
|
351
|
+
if not list_of_lists or list_of_lists in [[], [[]]]:
|
|
352
|
+
return []
|
|
353
|
+
|
|
354
|
+
# Find the maximum length of the sublists
|
|
355
|
+
lengths = [len(sublist) for sublist in list_of_lists]
|
|
356
|
+
max_length = max(lengths)
|
|
357
|
+
min_length = min(lengths)
|
|
358
|
+
if min_length == max_length: return list_of_lists
|
|
359
|
+
|
|
360
|
+
# Pad each sublist with empty strings to match the maximum length
|
|
361
|
+
padded_list = [sublist + [''] * (max_length - len(sublist)) for sublist in list_of_lists]
|
|
362
|
+
|
|
363
|
+
return padded_list
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
listpick/__init__.py,sha256=ExXc97-bibodH--wlwpQivl0zCNR5D1hvpvrf7OBofU,154
|
|
2
2
|
listpick/__main__.py,sha256=wkCjDdqw093W27yWwnlC3nG_sMRKaIad7hHHWy0RBgY,193
|
|
3
|
-
listpick/listpick_app.py,sha256=
|
|
3
|
+
listpick/listpick_app.py,sha256=xCtAMJTeWwos2XTCN7PwZgEgo3lAKmsp74M0cNgyvUI,165274
|
|
4
4
|
listpick/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
listpick/ui/build_help.py,sha256=_rVKKrX3HfFJtw-pyeNb2lQWbml4-AAw8sZIUYGn97Y,8731
|
|
6
6
|
listpick/ui/footer.py,sha256=s1L68MNmhWwbWRy0mn0ChmnE_dMQBAzNlTv917pyHE0,10673
|
|
7
|
-
listpick/ui/footer_1.py,sha256=Mpn0gFAnX_Ely-Jl5KPP6sdZRnk8makt8EVBh9wdr4Y,10710
|
|
8
7
|
listpick/ui/help_screen.py,sha256=zbfGIgb-IXtATpl4_Sx7nPbsnRXZ7eiMYlCKGS9EFmw,5608
|
|
9
8
|
listpick/ui/input_field.py,sha256=eyoWHoApdZybjfXcp7Eth7xwb-C-856ZVnq5j_Q3Ojs,30412
|
|
10
9
|
listpick/ui/keys.py,sha256=TzaadgBP_rC7jbp--RFJZDOkHd0EB4K1wToDTiVs6CI,13029
|
|
@@ -23,10 +22,10 @@ listpick/utils/search_and_filter_utils.py,sha256=XxGfkyDVXO9OAKcftPat8IReMTFIuTH
|
|
|
23
22
|
listpick/utils/searching.py,sha256=Xk5UIqamNHL2L90z3ACB_Giqdpi9iRKoAJ6pKaqaD7Q,3093
|
|
24
23
|
listpick/utils/sorting.py,sha256=WZZiVlVA3Zkcpwji3U5SNFlQ14zVEk3cZJtQirBkecQ,5329
|
|
25
24
|
listpick/utils/table_to_list_of_lists.py,sha256=T-i-nV1p6g8UagdgUPKrhIGpKY_YXZDxf4xZzcPepNA,7635
|
|
26
|
-
listpick/utils/utils.py,sha256=
|
|
27
|
-
listpick-0.1.13.
|
|
28
|
-
listpick-0.1.13.
|
|
29
|
-
listpick-0.1.13.
|
|
30
|
-
listpick-0.1.13.
|
|
31
|
-
listpick-0.1.13.
|
|
32
|
-
listpick-0.1.13.
|
|
25
|
+
listpick/utils/utils.py,sha256=m4uzL2ZPVpFuboIola0_ZIfLzlbGqirdz0_oo61tIlU,13636
|
|
26
|
+
listpick-0.1.13.61.dist-info/licenses/LICENSE.txt,sha256=2mP-MRHJptADDNE9VInMNg1tE-C6Qv93Z4CCQKrpg9w,1061
|
|
27
|
+
listpick-0.1.13.61.dist-info/METADATA,sha256=VPjp9FR1XNwseaF4k0z4jyEHp3J7qXqXe3vFVlMXZrQ,7988
|
|
28
|
+
listpick-0.1.13.61.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
29
|
+
listpick-0.1.13.61.dist-info/entry_points.txt,sha256=-QCf_BKIkUz35Y9nkYpjZWs2Qg0KfRna2PAs5DnF6BE,43
|
|
30
|
+
listpick-0.1.13.61.dist-info/top_level.txt,sha256=5mtsGEz86rz3qQDe0D463gGjAfSp6A3EWg4J4AGYr-Q,9
|
|
31
|
+
listpick-0.1.13.61.dist-info/RECORD,,
|
listpick/ui/footer_1.py
DELETED
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
footer.py
|
|
3
|
-
Lines to be displayed on the help screen.
|
|
4
|
-
|
|
5
|
-
Author: GrimAndGreedy
|
|
6
|
-
License: MIT
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
import curses
|
|
10
|
-
import logging
|
|
11
|
-
|
|
12
|
-
logger = logging.getLogger('picker_log')
|
|
13
|
-
|
|
14
|
-
class Footer:
|
|
15
|
-
def __init__(self, stdscr, colours_start, get_state_function):
|
|
16
|
-
"""
|
|
17
|
-
stdscr: curses screen object
|
|
18
|
-
colours_start: base colour pair index
|
|
19
|
-
get_state_callback: function that returns a dict with all required data for rendering
|
|
20
|
-
"""
|
|
21
|
-
self.stdscr = stdscr
|
|
22
|
-
self.colours_start = colours_start
|
|
23
|
-
self.get_state = get_state_function
|
|
24
|
-
self.height = 0
|
|
25
|
-
|
|
26
|
-
def draw(self, h, w):
|
|
27
|
-
"""
|
|
28
|
-
Draw the footer. Must be implemented by subclasses.
|
|
29
|
-
"""
|
|
30
|
-
raise NotImplementedError
|
|
31
|
-
|
|
32
|
-
class StandardFooter(Footer):
|
|
33
|
-
def __init__(self, stdscr, colours_start, get_state_function):
|
|
34
|
-
"""
|
|
35
|
-
stdscr: curses screen object
|
|
36
|
-
colours_start: base colour pair index
|
|
37
|
-
get_state_callback: function that returns a dict with all required data for rendering
|
|
38
|
-
"""
|
|
39
|
-
self.stdscr = stdscr
|
|
40
|
-
self.colours_start = colours_start
|
|
41
|
-
self.get_state = get_state_function
|
|
42
|
-
self.height = 3
|
|
43
|
-
def draw(self, h, w):
|
|
44
|
-
state = self.get_state()
|
|
45
|
-
|
|
46
|
-
# Fill background
|
|
47
|
-
for i in range(3):
|
|
48
|
-
self.stdscr.addstr(h-3+i, 0, ' '*(w-1), curses.color_pair(self.colours_start+20))
|
|
49
|
-
|
|
50
|
-
if state["filter_query"]:
|
|
51
|
-
self.stdscr.addstr(h - 2, 2, f" Filter: {state['filter_query']} "[:w-40], curses.color_pair(self.colours_start+20) | curses.A_BOLD)
|
|
52
|
-
if state["search_query"]:
|
|
53
|
-
self.stdscr.addstr(h - 3, 2, f" Search: {state['search_query']} [{state['search_index']}/{state['search_count']}] "[:w-3], curses.color_pair(self.colours_start+20) | curses.A_BOLD)
|
|
54
|
-
if state["user_opts"]:
|
|
55
|
-
self.stdscr.addstr(h - 1, 2, f" Opts: {state['user_opts']} "[:w-3], curses.color_pair(self.colours_start+20) | curses.A_BOLD)
|
|
56
|
-
|
|
57
|
-
# Sort info
|
|
58
|
-
sort_column_info = f"{state['sort_column'] if state['sort_column'] is not None else 'None'}"
|
|
59
|
-
sort_method_info = f"{state['SORT_METHODS'][state['columns_sort_method'][state['sort_column']]]}" if state['sort_column'] is not None else "NA"
|
|
60
|
-
sort_order_info = "Desc." if state["sort_reverse"] else "Asc."
|
|
61
|
-
sort_order_info = "▼" if state["sort_reverse"][state['sort_column']] else "▲"
|
|
62
|
-
sort_disp_str = f" Sort: ({sort_column_info}, {sort_method_info}, {sort_order_info}) "
|
|
63
|
-
self.stdscr.addstr(h - 2, w-35, f"{sort_disp_str:>34}", curses.color_pair(self.colours_start+20))
|
|
64
|
-
|
|
65
|
-
if state["footer_string"]:
|
|
66
|
-
# footer_string_width = min(w-1, max(len(state["footer_string"]), 50))
|
|
67
|
-
# disp_string = f"{state['footer_string'][:footer_string_width]:>{footer_string_width-1}} "
|
|
68
|
-
# self.stdscr.addstr(h - 1, w-footer_string_width-1, " "*footer_string_width, curses.color_pair(self.colours_start+24))
|
|
69
|
-
# self.stdscr.addstr(h - 1, w-footer_string_width-1, f"{disp_string}", curses.color_pair(self.colours_start+24))
|
|
70
|
-
|
|
71
|
-
# disp_string = f"{footer_string:>{footer_string_width-1}} "
|
|
72
|
-
# self.stdscr.addstr(h - 1, w-footer_string_width-1, " "*footer_string_width, curses.color_pair(self.colours_start+24))
|
|
73
|
-
# self.stdscr.addstr(h - 1, w-footer_string_width-1, f"{disp_string}", curses.color_pair(self.colours_start+24))
|
|
74
|
-
|
|
75
|
-
footer_string_width = min(w-1, len(state["footer_string"])+2)
|
|
76
|
-
|
|
77
|
-
disp_string = f"{state["footer_string"][:footer_string_width]}"
|
|
78
|
-
disp_string = f" {disp_string:>{footer_string_width-2}} "
|
|
79
|
-
self.stdscr.addstr(h - 1, w-footer_string_width-1, " "*footer_string_width, curses.color_pair(self.colours_start+24))
|
|
80
|
-
self.stdscr.addstr(h - 1, w-footer_string_width-1, f"{disp_string}", curses.color_pair(self.colours_start+24))
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
else:
|
|
84
|
-
select_mode = "Cursor"
|
|
85
|
-
if state["is_selecting"]: select_mode = "Visual Selection"
|
|
86
|
-
elif state["is_deselecting"]: select_mode = "Visual deselection"
|
|
87
|
-
self.stdscr.addstr(h - 1, w-35, f"{select_mode:>33} ", curses.color_pair(self.colours_start+20))
|
|
88
|
-
|
|
89
|
-
# Cursor & selection info
|
|
90
|
-
selected_count = sum(state["selections"].values())
|
|
91
|
-
if state["paginate"]:
|
|
92
|
-
cursor_disp_str = f" {state['cursor_pos']+1}/{len(state['indexed_items'])} Page {state['cursor_pos']//state['items_per_page']}/{len(state['indexed_items'])} Selected {selected_count}"
|
|
93
|
-
else:
|
|
94
|
-
cursor_disp_str = f" {state['cursor_pos']+1}/{len(state['indexed_items'])} | Selected {selected_count}"
|
|
95
|
-
self.stdscr.addstr(h - 3, w-35, f"{cursor_disp_str:>33} ", curses.color_pair(self.colours_start+20))
|
|
96
|
-
|
|
97
|
-
self.stdscr.refresh()
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
class CompactFooter(Footer):
|
|
102
|
-
def __init__(self, stdscr, colours_start, get_state_function):
|
|
103
|
-
"""
|
|
104
|
-
stdscr: curses screen object
|
|
105
|
-
colours_start: base colour pair index
|
|
106
|
-
get_state_callback: function that returns a dict with all required data for rendering
|
|
107
|
-
"""
|
|
108
|
-
self.stdscr = stdscr
|
|
109
|
-
self.colours_start = colours_start
|
|
110
|
-
self.get_state = get_state_function
|
|
111
|
-
self.height = 1
|
|
112
|
-
|
|
113
|
-
def draw(self, h, w):
|
|
114
|
-
state = self.get_state()
|
|
115
|
-
|
|
116
|
-
# Fill background
|
|
117
|
-
if state["search_query"]: self.height = 3
|
|
118
|
-
elif state["filter_query"]: self.height = 2
|
|
119
|
-
elif state["user_opts"]: self.height = 1
|
|
120
|
-
elif state["footer_string"]: self.height = 2
|
|
121
|
-
else: self.height = 1
|
|
122
|
-
for i in range(self.height):
|
|
123
|
-
self.stdscr.addstr(h-(i+1), 0, ' '*(w-1), curses.color_pair(self.colours_start+20))
|
|
124
|
-
|
|
125
|
-
if state["user_opts"]:
|
|
126
|
-
self.stdscr.addstr(h - 1, 2, f" Opts: {state['user_opts']} "[:w-3], curses.color_pair(self.colours_start+20) | curses.A_BOLD)
|
|
127
|
-
if state["filter_query"]:
|
|
128
|
-
self.stdscr.addstr(h - 2, 2, f" Filter: {state['filter_query']} "[:w-40], curses.color_pair(self.colours_start+20) | curses.A_BOLD)
|
|
129
|
-
if state["search_query"]:
|
|
130
|
-
self.stdscr.addstr(h - 3, 2, f" Search: {state['search_query']} [{state['search_index']}/{state['search_count']}] "[:w-3], curses.color_pair(self.colours_start+20) | curses.A_BOLD)
|
|
131
|
-
|
|
132
|
-
right_width = 40
|
|
133
|
-
# Sort info
|
|
134
|
-
sort_column_info = f"{state['sort_column'] if state['sort_column'] is not None else 'None'}"
|
|
135
|
-
sort_method_info = f"{state['SORT_METHODS'][state['columns_sort_method'][state['sort_column']]]}" if state['sort_column'] is not None else "NA"
|
|
136
|
-
sort_order_info = "Desc." if state["sort_reverse"][state['sort_column']] else "Asc."
|
|
137
|
-
sort_order_info = "▼" if state["sort_reverse"][state['sort_column']] else "▲"
|
|
138
|
-
sort_disp_str = f" ({sort_column_info}, {sort_method_info}, {sort_order_info}) "
|
|
139
|
-
# self.stdscr.addstr(h - 2, w-right_width, f"{sort_disp_str:>{right_width-1}}", curses.color_pair(self.colours_start+20))
|
|
140
|
-
|
|
141
|
-
if state["footer_string"]:
|
|
142
|
-
footer_string_width = min(w-1, len(state["footer_string"])+2)
|
|
143
|
-
|
|
144
|
-
disp_string = f"{state["footer_string"][:footer_string_width]}"
|
|
145
|
-
disp_string = f" {disp_string:>{footer_string_width-2}} "
|
|
146
|
-
self.stdscr.addstr(h - 1, w-footer_string_width-1, " "*footer_string_width, curses.color_pair(self.colours_start+24))
|
|
147
|
-
self.stdscr.addstr(h - 1, w-footer_string_width-1, f"{disp_string}", curses.color_pair(self.colours_start+24))
|
|
148
|
-
selected_count = sum(state["selections"].values())
|
|
149
|
-
if state["paginate"]:
|
|
150
|
-
cursor_disp_str = f" {state['cursor_pos']+1}/{len(state['indexed_items'])} Page {state['cursor_pos']//state['items_per_page']}/{len(state['indexed_items'])} Selected {selected_count}"
|
|
151
|
-
else:
|
|
152
|
-
cursor_disp_str = f"{sort_disp_str} [{selected_count}] {state['cursor_pos']+1}/{len(state['indexed_items'])}"
|
|
153
|
-
self.stdscr.addstr(h-2, w-right_width, f"{cursor_disp_str:>{right_width-2}}"[:right_width-1], curses.color_pair(self.colours_start+20))
|
|
154
|
-
else:
|
|
155
|
-
# Cursor & selection info
|
|
156
|
-
selected_count = sum(state["selections"].values())
|
|
157
|
-
if state["paginate"]:
|
|
158
|
-
cursor_disp_str = f" {state['cursor_pos']+1}/{len(state['indexed_items'])} Page {state['cursor_pos']//state['items_per_page']}/{len(state['indexed_items'])} Selected {selected_count}"
|
|
159
|
-
else:
|
|
160
|
-
cursor_disp_str = f"{sort_disp_str} [{selected_count}] {state['cursor_pos']+1}/{len(state['indexed_items'])}"
|
|
161
|
-
self.stdscr.addstr(h - 1, w-right_width, f"{cursor_disp_str:>{right_width-2}}"[:right_width-1], curses.color_pair(self.colours_start+20))
|
|
162
|
-
|
|
163
|
-
self.stdscr.refresh()
|
|
164
|
-
|
|
165
|
-
class NoFooter(Footer):
|
|
166
|
-
def __init__(self, stdscr, colours_start, get_state_function):
|
|
167
|
-
"""
|
|
168
|
-
stdscr: curses screen object
|
|
169
|
-
colours_start: base colour pair index
|
|
170
|
-
get_state_callback: function that returns a dict with all required data for rendering
|
|
171
|
-
"""
|
|
172
|
-
self.stdscr = stdscr
|
|
173
|
-
self.colours_start = colours_start
|
|
174
|
-
self.get_state = get_state_function
|
|
175
|
-
self.height = 0
|
|
176
|
-
def draw(self, h, w):
|
|
177
|
-
state = self.get_state()
|
|
178
|
-
|
|
179
|
-
if state["search_query"]: self.height = 3
|
|
180
|
-
elif state["filter_query"]: self.height = 2
|
|
181
|
-
elif state["user_opts"]: self.height = 1
|
|
182
|
-
elif state["footer_string"]: self.height = 1
|
|
183
|
-
else: self.height = 0
|
|
184
|
-
|
|
185
|
-
for i in range(self.height):
|
|
186
|
-
self.stdscr.addstr(h-(i+1), 0, ' '*(w-1), curses.color_pair(self.colours_start+20))
|
|
187
|
-
|
|
188
|
-
if state["user_opts"]:
|
|
189
|
-
self.stdscr.addstr(h - 1, 2, f" Opts: {state['user_opts']} "[:w-3], curses.color_pair(self.colours_start+20) | curses.A_BOLD)
|
|
190
|
-
if state["filter_query"]:
|
|
191
|
-
self.stdscr.addstr(h - 2, 2, f" Filter: {state['filter_query']} "[:w-40], curses.color_pair(self.colours_start+20) | curses.A_BOLD)
|
|
192
|
-
if state["search_query"]:
|
|
193
|
-
self.stdscr.addstr(h - 3, 2, f" Search: {state['search_query']} [{state['search_index']}/{state['search_count']}] "[:w-3], curses.color_pair(self.colours_start+20) | curses.A_BOLD)
|
|
194
|
-
self.height = 3
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
if state["footer_string"]:
|
|
198
|
-
footer_string_width = min(w-1, len(state["footer_string"])+2)
|
|
199
|
-
disp_string = f"{state["footer_string"][:footer_string_width]}"
|
|
200
|
-
disp_string = f" {disp_string:>{footer_string_width-2}} "
|
|
201
|
-
self.stdscr.addstr(h - 1, w-footer_string_width-1, " "*footer_string_width, curses.color_pair(self.colours_start+24))
|
|
202
|
-
self.stdscr.addstr(h - 1, w-footer_string_width-1, f"{disp_string}", curses.color_pair(self.colours_start+24))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|