listpick 0.1.13.55__py3-none-any.whl → 0.1.13.56__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/ui/footer.py CHANGED
@@ -39,39 +39,21 @@ class StandardFooter(Footer):
39
39
  self.stdscr = stdscr
40
40
  self.colours_start = colours_start
41
41
  self.get_state = get_state_function
42
- self.height = 3
42
+
43
+ self.height = 2
44
+ try:
45
+ state = self.get_state()
46
+ if "footer_string" in state and state["footer_string"]: self.height = 3
47
+ else: self.height = 2
48
+ except:
49
+ logger.error("Error encountered when running StandardFooter.get_state")
43
50
  def draw(self, h, w):
44
51
  state = self.get_state()
45
-
46
52
  # 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))
53
+ for i in range(self.height):
54
+ self.stdscr.addstr(h-self.height+i, 0, ' '*(w-1), curses.color_pair(self.colours_start+20))
64
55
 
65
56
  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
57
  footer_string_width = min(w-1, len(state["footer_string"])+2)
76
58
 
77
59
  disp_string = f"{state["footer_string"][:footer_string_width]}"
@@ -79,20 +61,51 @@ class StandardFooter(Footer):
79
61
  self.stdscr.addstr(h - 1, w-footer_string_width-1, " "*footer_string_width, curses.color_pair(self.colours_start+24))
80
62
  self.stdscr.addstr(h - 1, w-footer_string_width-1, f"{disp_string}", curses.color_pair(self.colours_start+24))
81
63
 
64
+ picker_info_y = h-3
65
+ sort_info_y = h-2
66
+ self.height = 3
82
67
 
83
68
  else:
84
- select_mode = "Cursor"
85
- if state["is_selecting"]: select_mode = "Visual Selection"
86
- elif state["is_deselecting"]: select_mode = "Visual deselection"
69
+ picker_info_y = h-2
70
+ sort_info_y = h-1
71
+ ""
72
+ select_mode = "C"
73
+ if state["is_selecting"]: select_mode = "VS"
74
+ elif state["is_deselecting"]: select_mode = "VDS"
75
+ if state["pin_cursor"]: select_mode = f"{select_mode} "
87
76
  self.stdscr.addstr(h - 1, w-35, f"{select_mode:>33} ", curses.color_pair(self.colours_start+20))
77
+ self.height = 2
78
+
79
+
80
+ if state["filter_query"]:
81
+ self.stdscr.addstr(h - 2, 2, f" Filter: {state['filter_query']} "[:w-40], curses.color_pair(self.colours_start+20) | curses.A_BOLD)
82
+ if state["search_query"]:
83
+ 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)
84
+ if state["user_opts"]:
85
+ self.stdscr.addstr(h - 1, 2, f" Opts: {state['user_opts']} "[:w-3], curses.color_pair(self.colours_start+20) | curses.A_BOLD)
86
+
88
87
 
88
+
89
+ select_mode = "C"
90
+ if state["is_selecting"]: select_mode = "VS"
91
+ elif state["is_deselecting"]: select_mode = "VDS"
92
+ if state["pin_cursor"]: select_mode = f"{select_mode} "
89
93
  # Cursor & selection info
90
94
  selected_count = sum(state["selections"].values())
91
95
  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}"
96
+ cursor_disp_str = f" [{selected_count}] {state['cursor_pos']+1}/{len(state['indexed_items'])} Page {state['cursor_pos']//state['items_per_page']}/{len(state['indexed_items'])}"
93
97
  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))
98
+ cursor_disp_str = f" [{selected_count}] {state['cursor_pos']+1}/{len(state['indexed_items'])} | {select_mode}"
99
+ self.stdscr.addstr(picker_info_y, w-35, f"{cursor_disp_str:>33} ", curses.color_pair(self.colours_start+20))
100
+
101
+
102
+ # Sort info
103
+ sort_column_info = f"{state['sort_column'] if state['sort_column'] is not None else 'None'}"
104
+ sort_method_info = f"{state['SORT_METHODS'][state['columns_sort_method'][state['sort_column']]]}" if state['sort_column'] is not None else "NA"
105
+ sort_order_info = "Desc." if state["sort_reverse"] else "Asc."
106
+ sort_order_info = "▼" if state["sort_reverse"][state['sort_column']] else "▲"
107
+ sort_disp_str = f" Sort: ({sort_column_info}, {sort_method_info}, {sort_order_info}) "
108
+ self.stdscr.addstr(sort_info_y, w-35, f"{sort_disp_str:>34}", curses.color_pair(self.colours_start+20))
96
109
 
97
110
  self.stdscr.refresh()
98
111
 
listpick/utils/utils.py CHANGED
@@ -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, unicode_char_width:bool = True) -> str:
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
- if unicode_char_width:
50
- result = ''
51
- width = 0
52
-
53
-
54
- for char in text:
55
- w = wcwidth(char)
56
- if w < 0:
57
- continue
58
- if width + w > max_column_width:
59
- break
60
- result += char
61
- width += w
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, unicode_char_width:bool = True) -> str:
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, unicode_char_width)
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 = " ", unicode_char_width:bool=True) -> list[int]:
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
- if unicode_char_width:
121
- widths = [max(wcswidth(str(row[i])) for row in items) for i in range(len(items[0]))]
122
- # widths = [max(len(str(row[i])) for row in items) for i in range(len(items[0]))]
123
- if header:
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
- widths = [max(len(str(row[i])) for row in items) for i in range(len(items[0]))]
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]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: listpick
3
- Version: 0.1.13.55
3
+ Version: 0.1.13.56
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
@@ -1,12 +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=6KULvZKkHpI8y0Z48Qo5_hrKfd1S3khdScLLJtlPIjI,166651
4
- listpick/listpick_app_1.py,sha256=6KULvZKkHpI8y0Z48Qo5_hrKfd1S3khdScLLJtlPIjI,166651
5
- listpick/lpapp2.py,sha256=x26FOsUPgwjiAecF8gGE8GbfCQF6eJGgf4hccqSZIBU,162376
3
+ listpick/listpick_app.py,sha256=DcijE4rOpAcEF1JE9H6G0iUbDgpYQO5QaSkf2VavfL4,161560
6
4
  listpick/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
5
  listpick/ui/build_help.py,sha256=_rVKKrX3HfFJtw-pyeNb2lQWbml4-AAw8sZIUYGn97Y,8731
8
- listpick/ui/footer.py,sha256=Mpn0gFAnX_Ely-Jl5KPP6sdZRnk8makt8EVBh9wdr4Y,10710
9
- listpick/ui/footer_1.py,sha256=po8abQfaVNoWxYJCw8fENENIdOvNmLIZYfuqTwagz00,10713
6
+ listpick/ui/footer.py,sha256=s1L68MNmhWwbWRy0mn0ChmnE_dMQBAzNlTv917pyHE0,10673
10
7
  listpick/ui/help_screen.py,sha256=zbfGIgb-IXtATpl4_Sx7nPbsnRXZ7eiMYlCKGS9EFmw,5608
11
8
  listpick/ui/input_field.py,sha256=eyoWHoApdZybjfXcp7Eth7xwb-C-856ZVnq5j_Q3Ojs,30412
12
9
  listpick/ui/keys.py,sha256=TzaadgBP_rC7jbp--RFJZDOkHd0EB4K1wToDTiVs6CI,13029
@@ -25,10 +22,10 @@ listpick/utils/search_and_filter_utils.py,sha256=XxGfkyDVXO9OAKcftPat8IReMTFIuTH
25
22
  listpick/utils/searching.py,sha256=Xk5UIqamNHL2L90z3ACB_Giqdpi9iRKoAJ6pKaqaD7Q,3093
26
23
  listpick/utils/sorting.py,sha256=WZZiVlVA3Zkcpwji3U5SNFlQ14zVEk3cZJtQirBkecQ,5329
27
24
  listpick/utils/table_to_list_of_lists.py,sha256=T-i-nV1p6g8UagdgUPKrhIGpKY_YXZDxf4xZzcPepNA,7635
28
- listpick/utils/utils.py,sha256=bEE7-g3cyZd4QFHOxo4P6lXmuo0NwHTS_ovFC92po5w,13826
29
- listpick-0.1.13.55.dist-info/licenses/LICENSE.txt,sha256=2mP-MRHJptADDNE9VInMNg1tE-C6Qv93Z4CCQKrpg9w,1061
30
- listpick-0.1.13.55.dist-info/METADATA,sha256=tfHsx31zDd3hpMCp1sGgTnVci5PrrOegqUVfswqPJoo,7988
31
- listpick-0.1.13.55.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
32
- listpick-0.1.13.55.dist-info/entry_points.txt,sha256=-QCf_BKIkUz35Y9nkYpjZWs2Qg0KfRna2PAs5DnF6BE,43
33
- listpick-0.1.13.55.dist-info/top_level.txt,sha256=5mtsGEz86rz3qQDe0D463gGjAfSp6A3EWg4J4AGYr-Q,9
34
- listpick-0.1.13.55.dist-info/RECORD,,
25
+ listpick/utils/utils.py,sha256=8nsjjTDQH13tHTU93YcKklLQ_uuMAz-rbDTmao83T4Q,12783
26
+ listpick-0.1.13.56.dist-info/licenses/LICENSE.txt,sha256=2mP-MRHJptADDNE9VInMNg1tE-C6Qv93Z4CCQKrpg9w,1061
27
+ listpick-0.1.13.56.dist-info/METADATA,sha256=mCnB_Vdd2nwucGm7IdpyuwFJ37RIA0kjEq9kBn6voxI,7988
28
+ listpick-0.1.13.56.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
29
+ listpick-0.1.13.56.dist-info/entry_points.txt,sha256=-QCf_BKIkUz35Y9nkYpjZWs2Qg0KfRna2PAs5DnF6BE,43
30
+ listpick-0.1.13.56.dist-info/top_level.txt,sha256=5mtsGEz86rz3qQDe0D463gGjAfSp6A3EWg4J4AGYr-Q,9
31
+ listpick-0.1.13.56.dist-info/RECORD,,