listpick 0.1.16.4__py3-none-any.whl → 0.1.16.6__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 CHANGED
@@ -20,8 +20,6 @@ import json
20
20
  import threading
21
21
  import string
22
22
  import logging
23
- import tty
24
- import select
25
23
 
26
24
  from listpick.pane.pane_utils import get_file_attributes
27
25
  from listpick.ui.picker_colours import get_colours, get_help_colours, get_notification_colours, get_theme_count, get_fallback_colours
@@ -36,22 +34,15 @@ from listpick.utils.paste_operations import *
36
34
  from listpick.utils.searching import search
37
35
  from listpick.ui.help_screen import help_lines
38
36
  from listpick.ui.keys import picker_keys, notification_keys, options_keys, help_keys
39
- # from listpick.utils.generate_data import generate_picker_data
40
37
  from listpick.utils.generate_data_multithreaded import generate_picker_data_from_file
41
38
  from listpick.utils.dump import dump_state, load_state, dump_data
42
39
  from listpick.ui.build_help import build_help_rows
43
40
  from listpick.ui.footer import StandardFooter, CompactFooter, NoFooter
44
41
  from listpick.utils.picker_log import setup_logger
45
- from listpick.utils.user_input import get_char, open_tty
42
+ from listpick.utils.user_input import get_char, open_tty, restore_terminal_settings
46
43
  from listpick.pane.pane_functions import right_split_file_attributes, right_split_file_attributes_dynamic, right_split_graph, right_split_display_list
47
44
  from listpick.pane.get_data import *
48
45
 
49
-
50
- try:
51
- from tmp.data_stuff import test_items, test_highlights, test_header
52
- except:
53
- test_items, test_highlights, test_header = [], [], []
54
-
55
46
  COLOURS_SET = False
56
47
  help_colours, notification_colours = {}, {}
57
48
 
@@ -414,6 +405,14 @@ class Picker:
414
405
  config = toml.load(f)
415
406
  return config
416
407
 
408
+ def update_term_size(self):
409
+ self.term_h, self.term_w = self.stdscr.getmaxyx()
410
+
411
+ def get_term_size(self):
412
+ return self.stdscr.getmaxyx()
413
+ w, h = os.get_terminal_size()
414
+ return h, w
415
+
417
416
  def calculate_section_sizes(self):
418
417
  """
419
418
  Calculte the following for the Picker:
@@ -428,8 +427,7 @@ class Picker:
428
427
  self.bottom_space = self.footer.height if self.show_footer else 0
429
428
 
430
429
  ## self.top_space
431
- h, w = self.stdscr.getmaxyx()
432
- self.term_h, self.term_w = self.stdscr.getmaxyx()
430
+ self.update_term_size()
433
431
  if self.split_right and len(self.right_panes):
434
432
  proportion = self.right_panes[self.right_pane_index]["proportion"]
435
433
  self.rows_w, self.rows_h = int(self.term_w*proportion), self.term_h
@@ -551,7 +549,7 @@ class Picker:
551
549
 
552
550
  # self.stdscr.clear()
553
551
  # self.stdscr.refresh()
554
- # self.draw_screen(self.indexed_items, self.highlights)
552
+ # self.draw_screen()
555
553
 
556
554
  def initialise_variables(self, get_data: bool = False) -> None:
557
555
  """ Initialise the variables that keep track of the data. """
@@ -759,13 +757,13 @@ class Picker:
759
757
 
760
758
  """
761
759
  self.logger.debug("function: test_screen_size()")
762
- h, w = self.stdscr.getmaxyx()
760
+ self.update_term_size()
763
761
  ## Terminal too small to display Picker
764
- if h<3 or w<len("Terminal"): return False
765
- if (self.show_footer or self.footer_string) and (h<12 or w<35) or (h<12 and w<10):
766
- self.stdscr.addstr(h//2-1, (w-len("Terminal"))//2, "Terminal")
767
- self.stdscr.addstr(h//2, (w-len("Too"))//2, "Too")
768
- self.stdscr.addstr(h//2+1, (w-len("Small"))//2, "Small")
762
+ if self.term_h<3 or self.term_w<len("Terminal"): return False
763
+ if (self.show_footer or self.footer_string) and (self.term_h<12 or self.term_w<35) or (self.term_h<12 and self.term_w<10):
764
+ self.stdscr.addstr(self.term_h//2-1, (self.term_w-len("Terminal"))//2, "Terminal")
765
+ self.stdscr.addstr(self.term_h//2, (self.term_w-len("Too"))//2, "Too")
766
+ self.stdscr.addstr(self.term_h//2+1, (self.term_w-len("Small"))//2, "Small")
769
767
  return False
770
768
  return True
771
769
 
@@ -778,28 +776,28 @@ class Picker:
778
776
 
779
777
  if type(message) == type(""): message = [message]
780
778
 
781
- h, w =self.stdscr.getmaxyx()
782
- if len(message) > h: start_y = 0
783
- else: start_y = (h-len(message))//2
779
+ self.update_term_size()
780
+ if len(message) > self.term_h: start_y = 0
781
+ else: start_y = (self.term_h-len(message))//2
784
782
 
785
783
  for i in range(len(message)):
786
784
  try:
787
785
  s = message[i]
788
- if len(s) > w: s = s[:w-2]
789
- self.stdscr.addstr(start_y+i, (w-len(s))//2, s, curses.color_pair(2))
786
+ if len(s) > self.term_w: s = s[:self.term_w-2]
787
+ self.stdscr.addstr(start_y+i, (self.term_w-len(s))//2, s, curses.color_pair(2))
790
788
  except:
791
789
  pass
792
790
  self.stdscr.refresh()
793
791
 
794
- def draw_screen(self, indexed_items: list[Tuple[int, list[str]]], highlights: list[dict] = [{}], clear: bool = True) -> None:
792
+ def draw_screen(self, clear: bool = True) -> None:
795
793
  """ Try-except wrapper for the draw_screen_ function. """
796
794
  try:
797
- self.draw_screen_(self.indexed_items, self.highlights)
795
+ self.draw_screen_(clear)
798
796
  except Exception as e:
799
797
  self.logger.warning(f"self.draw_screen_() error. {e}")
800
798
  pass
801
799
 
802
- def draw_screen_(self, indexed_items: list[Tuple[int, list[str]]], highlights: list[dict] = [{}], clear: bool = True) -> None:
800
+ def draw_screen_(self, clear: bool = True) -> None:
803
801
  """ Draw Picker screen. """
804
802
 
805
803
  self.logger.debug("Draw screen.")
@@ -807,8 +805,7 @@ class Picker:
807
805
  if clear:
808
806
  self.stdscr.erase()
809
807
 
810
- h, w = self.stdscr.getmaxyx()
811
- self.term_h, self.term_w = self.stdscr.getmaxyx()
808
+ self.update_term_size()
812
809
  if self.split_right and len(self.right_panes):
813
810
  proportion = self.right_panes[self.right_pane_index]["proportion"]
814
811
  self.rows_w, self.rows_h = int(self.term_w*proportion), self.term_h
@@ -846,7 +843,7 @@ class Picker:
846
843
 
847
844
  # Determine the number of items_per_page, top_size and bottom_size
848
845
  # self.calculate_section_sizes()
849
-
846
+
850
847
  # top_space = self.top_gap
851
848
 
852
849
  ## Display title (if applicable)
@@ -918,11 +915,11 @@ class Picker:
918
915
  # Start of selected column is on the screen
919
916
  if self.leftmost_char <= len(up_to_selected_col) and self.leftmost_char+self.rows_w-self.startx > len(up_to_selected_col):
920
917
  x_pos = len(up_to_selected_col) - self.leftmost_char + self.startx
921
-
918
+
922
919
  # Whole cell of the selected column is on the screen
923
920
  if len(up_to_selected_col)+col_width - self.leftmost_char < self.rows_w-self.startx:
924
921
  disp_str = highlighted_col_str
925
-
922
+
926
923
  # Start of the cell is on the screen, but the end of the cell is not
927
924
  else:
928
925
  overflow = (len(up_to_selected_col)+len(highlighted_col_str)) - (self.leftmost_char+self.rows_w - self.startx)
@@ -974,7 +971,7 @@ class Picker:
974
971
  # self.stdscr.addstr(header_ypos, highlighed_col_startx , highlighted_col_str[start_of_highlighted_col_str:end_of_highlighted_col_str][:self.column_widths[self.selected_column]+len(self.separator)], curses.color_pair(self.colours_start+19) | curses.A_BOLD)
975
972
  except:
976
973
  pass
977
-
974
+
978
975
  # Display row header
979
976
  if self.show_row_header:
980
977
  for idx in range(start_index, end_index):
@@ -986,7 +983,7 @@ class Picker:
986
983
 
987
984
 
988
985
  def highlight_cell(row: int, col:int, visible_column_widths, colour_pair_number: int = 5, bold: bool = False, y:int = 0):
989
-
986
+
990
987
  cell_pos = sum(visible_column_widths[:col])+col*len(self.separator)-self.leftmost_char + self.startx
991
988
  # cell_width = self.column_widths[self.selected_column]
992
989
  cell_width = visible_column_widths[col] + len(self.separator)
@@ -1119,7 +1116,7 @@ class Picker:
1119
1116
 
1120
1117
  ## Display the standard row
1121
1118
  self.stdscr.addstr(y, self.startx, row_str[:min(self.rows_w-self.startx, visible_columns_total_width)], curses.color_pair(self.colours_start+2))
1122
-
1119
+
1123
1120
 
1124
1121
  ## Highlight column
1125
1122
  if self.crosshair_cursor:
@@ -1190,7 +1187,7 @@ class Picker:
1190
1187
  highlight_cell(idx, self.selected_column, visible_column_widths, colour_pair_number=5, bold=True, y=y)
1191
1188
  else:
1192
1189
  self.stdscr.addstr(y, self.startx, row_str[:min(self.rows_w-self.startx, visible_columns_total_width)], curses.color_pair(self.colours_start+5) | curses.A_BOLD)
1193
-
1190
+
1194
1191
  if not self.highlights_hide:
1195
1192
  draw_highlights(l2_highlights, idx, y, item)
1196
1193
 
@@ -1226,7 +1223,6 @@ class Picker:
1226
1223
  ## Display footer
1227
1224
  if self.show_footer:
1228
1225
  # self.footer = NoFooter(self.stdscr, self.colours_start, self.get_function_data)
1229
- h, w = self.stdscr.getmaxyx()
1230
1226
  try:
1231
1227
  self.footer.draw(self.term_h, self.term_w)
1232
1228
  except:
@@ -1259,7 +1255,7 @@ class Picker:
1259
1255
  cell = self.indexed_items[self.cursor_pos][1][self.selected_column] if self.indexed_items else "",
1260
1256
  data=data,
1261
1257
  )
1262
-
1258
+
1263
1259
  self.stdscr.refresh()
1264
1260
  ## Display infobox
1265
1261
  if self.display_infobox:
@@ -1272,8 +1268,10 @@ class Picker:
1272
1268
  """ Display non-interactive infobox window. """
1273
1269
 
1274
1270
  self.logger.info(f"function: infobox()")
1275
- h, w = stdscr.getmaxyx()
1276
- notification_width, notification_height = w//2, 3*h//5
1271
+ self.update_term_size()
1272
+
1273
+
1274
+ notification_width, notification_height = self.term_w//2, 3*self.term_h//5
1277
1275
  message_width = notification_width-5
1278
1276
 
1279
1277
  if not message: message = "!!"
@@ -1289,9 +1287,9 @@ class Picker:
1289
1287
  if len(submenu_items) > notification_height - 2:
1290
1288
  submenu_items = submenu_items[:notification_height-3] + [f"{'....':^{notification_width}}"]
1291
1289
  while True:
1292
- h, w = stdscr.getmaxyx()
1293
1290
 
1294
- submenu_win = curses.newwin(notification_height, notification_width, 3, w - (notification_width+4))
1291
+ self.update_term_size()
1292
+ submenu_win = curses.newwin(notification_height, notification_width, 3, self.term_w - (notification_width+4))
1295
1293
  infobox_data = {
1296
1294
  "items": submenu_items,
1297
1295
  "colours": notification_colours,
@@ -1501,7 +1499,7 @@ class Picker:
1501
1499
  self.selections = {i:False for i in range(len(self.indexed_items))}
1502
1500
  self.cursor_pos = min(self.cursor_pos, len(self.indexed_items)-1)
1503
1501
  self.initialise_variables()
1504
- self.draw_screen(self.indexed_items, self.highlights)
1502
+ self.draw_screen()
1505
1503
 
1506
1504
 
1507
1505
  def choose_option(
@@ -1558,19 +1556,19 @@ class Picker:
1558
1556
  "crosshair_cursor": False,
1559
1557
  }
1560
1558
  while True:
1561
- h, w = stdscr.getmaxyx()
1559
+ self.update_term_size()
1562
1560
 
1563
1561
  choose_opts_widths = get_column_widths(options, unicode_char_width=self.unicode_char_width)
1564
- window_width = min(max(sum(choose_opts_widths) + 6, 50) + 6, w)
1565
- window_height = min(h//2, max(6, len(options)+3))
1562
+ window_width = min(max(sum(choose_opts_widths) + 6, 50) + 6, self.term_w)
1563
+ window_height = min(self.term_h//2, max(6, len(options)+3))
1566
1564
 
1567
- submenu_win = curses.newwin(window_height, window_width, (h-window_height)//2, (w-window_width)//2)
1565
+ submenu_win = curses.newwin(window_height, window_width, (self.term_h-window_height)//2, (self.term_w-window_width)//2)
1568
1566
  submenu_win.keypad(True)
1569
1567
  OptionPicker = Picker(submenu_win, **option_picker_data)
1570
1568
  s, o, f = OptionPicker.run()
1571
1569
 
1572
1570
  if o == "refresh":
1573
- self.draw_screen(self.indexed_items, self.highlights)
1571
+ self.draw_screen()
1574
1572
  continue
1575
1573
  if s:
1576
1574
  return {x: options[x] for x in s}, o, f
@@ -1595,9 +1593,9 @@ class Picker:
1595
1593
  27: ord('q')
1596
1594
  }
1597
1595
  while True:
1598
- h, w = stdscr.getmaxyx()
1596
+ self.update_term_size()
1599
1597
 
1600
- submenu_win = curses.newwin(notification_height, notification_width, 3, w - (notification_width+4))
1598
+ submenu_win = curses.newwin(notification_height, notification_width, 3, self.term_w - (notification_width+4))
1601
1599
  notification_data = {
1602
1600
  "items": submenu_items,
1603
1601
  "title": title,
@@ -1628,7 +1626,7 @@ class Picker:
1628
1626
  del submenu_win
1629
1627
  stdscr.clear()
1630
1628
  stdscr.refresh()
1631
- self.draw_screen(self.indexed_items, self.highlights)
1629
+ self.draw_screen()
1632
1630
  # set_colours(colours=get_colours(0))
1633
1631
 
1634
1632
  def toggle_column_visibility(self, col_index:int) -> None:
@@ -1735,7 +1733,7 @@ class Picker:
1735
1733
  elif setting == "file_prev":
1736
1734
  self.command_stack.append(Command("setting", self.user_settings))
1737
1735
  self.switch_file(increment=-1)
1738
- # self.draw_screen(self.indexed_items, self.highlights)
1736
+ # self.draw_screen()
1739
1737
  # self.stdscr.refresh()
1740
1738
 
1741
1739
  elif setting == "sheet_next":
@@ -1799,7 +1797,7 @@ class Picker:
1799
1797
  theme_number = int(setting[2:].strip())
1800
1798
  self.colour_theme_number = min(get_theme_count()-1, theme_number)
1801
1799
  set_colours(self.colour_theme_number)
1802
- self.draw_screen(self.indexed_items, self.highlights)
1800
+ self.draw_screen()
1803
1801
  self.notification(self.stdscr, message=f"Theme {self.colour_theme_number} applied.")
1804
1802
  except:
1805
1803
  pass
@@ -1808,7 +1806,7 @@ class Picker:
1808
1806
  self.colour_theme_number = (self.colour_theme_number + 1)%get_theme_count()
1809
1807
  # self.colour_theme_number = int(not bool(self.colour_theme_number))
1810
1808
  set_colours(self.colour_theme_number)
1811
- self.draw_screen(self.indexed_items, self.highlights)
1809
+ self.draw_screen()
1812
1810
  self.notification(self.stdscr, message=f"Theme {self.colour_theme_number} applied.")
1813
1811
 
1814
1812
  else:
@@ -1834,7 +1832,7 @@ class Picker:
1834
1832
  """ Toggle selection of item at index. """
1835
1833
  self.logger.info(f"function: toggle_item()")
1836
1834
  self.selections[index] = not self.selections[index]
1837
- self.draw_screen(self.indexed_items, self.highlights)
1835
+ self.draw_screen()
1838
1836
 
1839
1837
  def select_all(self) -> None:
1840
1838
  """ Select all in indexed_items. """
@@ -1845,7 +1843,7 @@ class Picker:
1845
1843
  self.cell_selections[i] = True
1846
1844
  for row in range(len(self.indexed_items)):
1847
1845
  self.selected_cells_by_row[row] = list(range(len(self.indexed_items[row][1])))
1848
- self.draw_screen(self.indexed_items, self.highlights)
1846
+ self.draw_screen()
1849
1847
 
1850
1848
  def deselect_all(self) -> None:
1851
1849
  """ Deselect all items in indexed_items. """
@@ -1855,7 +1853,7 @@ class Picker:
1855
1853
  for i in self.cell_selections.keys():
1856
1854
  self.cell_selections[i] = False
1857
1855
  self.selected_cells_by_row = {}
1858
- self.draw_screen(self.indexed_items, self.highlights)
1856
+ self.draw_screen()
1859
1857
 
1860
1858
  def handle_visual_selection(self, selecting:bool = True) -> None:
1861
1859
  """ Toggle visual selection or deselection. """
@@ -1899,7 +1897,7 @@ class Picker:
1899
1897
  self.end_selection = -1
1900
1898
  self.is_selecting = False
1901
1899
 
1902
- self.draw_screen(self.indexed_items, self.highlights)
1900
+ self.draw_screen()
1903
1901
 
1904
1902
  elif self.is_deselecting:
1905
1903
  self.end_selection = self.indexed_items[self.cursor_pos][0]
@@ -1932,7 +1930,7 @@ class Picker:
1932
1930
  self.start_selection = -1
1933
1931
  self.end_selection = -1
1934
1932
  self.is_deselecting = False
1935
- self.draw_screen(self.indexed_items, self.highlights)
1933
+ self.draw_screen()
1936
1934
 
1937
1935
  def cursor_down(self, count=1) -> bool:
1938
1936
  """ Move cursor down. """
@@ -2050,12 +2048,12 @@ class Picker:
2050
2048
  if not acceptable_data_type:
2051
2049
  break
2052
2050
  if not acceptable_data_type:
2053
- self.draw_screen(self.indexed_items, self.highlights)
2051
+ self.draw_screen()
2054
2052
  self.notification(self.stdscr, message="Error pasting data.")
2055
2053
  return None
2056
2054
 
2057
2055
  except:
2058
- self.draw_screen(self.indexed_items, self.highlights)
2056
+ self.draw_screen()
2059
2057
  self.notification(self.stdscr, message="Error pasting data.")
2060
2058
  return None
2061
2059
  if type(pasta) == type([]) and len(pasta) > 0 and type(pasta[0]) == type([]):
@@ -2102,7 +2100,7 @@ class Picker:
2102
2100
  for idx in s.keys():
2103
2101
  save_path_entered, save_path = output_file_option_selector(
2104
2102
  self.stdscr,
2105
- refresh_screen_function=lambda: self.draw_screen(self.indexed_items, self.highlights)
2103
+ refresh_screen_function=lambda: self.draw_screen()
2106
2104
  )
2107
2105
  if save_path_entered:
2108
2106
  return_val = funcs[idx](save_path)
@@ -2136,7 +2134,7 @@ class Picker:
2136
2134
  self.loaded_file_states[self.loaded_file_index] = self.get_function_data()
2137
2135
 
2138
2136
  self.stdscr.clear()
2139
- self.draw_screen(self.indexed_items, self.highlights)
2137
+ self.draw_screen()
2140
2138
 
2141
2139
  tmp = self.stdscr
2142
2140
 
@@ -2156,7 +2154,7 @@ class Picker:
2156
2154
  # header = return_val["header"]
2157
2155
  self.stdscr.clear()
2158
2156
  # self.initialise_variables()
2159
- self.draw_screen(self.indexed_items, self.highlights)
2157
+ self.draw_screen()
2160
2158
  # self.stdscr.refresh()
2161
2159
 
2162
2160
  # if return_val:
@@ -2400,7 +2398,7 @@ class Picker:
2400
2398
 
2401
2399
  self.initialise_variables(get_data=self.get_data_startup)
2402
2400
 
2403
- self.draw_screen(self.indexed_items, self.highlights)
2401
+ self.draw_screen()
2404
2402
 
2405
2403
  self.initial_time = time.time()
2406
2404
  self.initial_time_footer = time.time()-self.footer_timer
@@ -2428,7 +2426,7 @@ class Picker:
2428
2426
 
2429
2427
  # Set terminal background color
2430
2428
  self.stdscr.bkgd(' ', curses.color_pair(self.colours_start+3)) # Apply background color
2431
- self.draw_screen(self.indexed_items, self.highlights)
2429
+ self.draw_screen()
2432
2430
 
2433
2431
  if self.display_only:
2434
2432
  self.stdscr.refresh()
@@ -2436,15 +2434,15 @@ class Picker:
2436
2434
  return [], "", function_data
2437
2435
 
2438
2436
  # Open tty to accept input
2439
- tty_fd = open_tty()
2437
+ tty_fd, self.saved_terminal_state = open_tty()
2440
2438
 
2441
- h, w = self.stdscr.getmaxyx()
2442
- self.term_h, self.term_w = self.stdscr.getmaxyx()
2439
+ self.update_term_size()
2443
2440
  if self.split_right and len(self.right_panes):
2444
2441
  proportion = self.right_panes[self.right_pane_index]["proportion"]
2445
2442
  self.rows_w, self.rows_h = int(self.term_w*proportion), self.term_h
2446
2443
  else:
2447
2444
  self.rows_w, self.rows_h = self.term_w, self.term_h
2445
+
2448
2446
  def terminal_resized(old_w, old_h) -> bool:
2449
2447
  w, h = os.get_terminal_size()
2450
2448
  if old_h != h or old_w != w: return True
@@ -2462,6 +2460,7 @@ class Picker:
2462
2460
  key = get_char(tty_fd, timeout=0.2)
2463
2461
  if key != -1:
2464
2462
  self.logger.info(f"key={key}")
2463
+ self.last_key = key
2465
2464
 
2466
2465
  # Ensure that
2467
2466
 
@@ -2478,8 +2477,7 @@ class Picker:
2478
2477
  if self.term_resize_event:
2479
2478
  key = curses.KEY_RESIZE
2480
2479
 
2481
- h, w = self.stdscr.getmaxyx()
2482
- self.term_h, self.term_w = self.stdscr.getmaxyx()
2480
+ self.update_term_size()
2483
2481
 
2484
2482
  if self.split_right and len(self.right_panes):
2485
2483
  proportion = self.right_panes[self.right_pane_index]["proportion"]
@@ -2500,7 +2498,7 @@ class Picker:
2500
2498
 
2501
2499
  self.initial_time = time.time()
2502
2500
 
2503
- self.draw_screen(self.indexed_items, self.highlights, clear=False)
2501
+ self.draw_screen(clear=False)
2504
2502
 
2505
2503
  self.refreshing_data = False
2506
2504
  self.data_ready = False
@@ -2536,7 +2534,7 @@ class Picker:
2536
2534
  self.logger.debug(f"footer_string_auto_refresh")
2537
2535
  self.footer_string = self.footer_string_refresh_function()
2538
2536
  self.initial_time_footer = time.time()
2539
- self.draw_screen(self.indexed_items, self.highlights)
2537
+ self.draw_screen()
2540
2538
 
2541
2539
  if self.split_right and len(self.right_panes) and self.right_panes[self.right_pane_index]["auto_refresh"] and ((time.time() - self.initial_split_time) > self.right_panes[self.right_pane_index]["refresh_time"]):
2542
2540
  get_data = self.right_panes[self.right_pane_index]["get_data"]
@@ -2572,7 +2570,7 @@ class Picker:
2572
2570
  }
2573
2571
  OptionPicker = Picker(self.stdscr, **help_data)
2574
2572
  s, o, f = OptionPicker.run()
2575
- self.draw_screen(self.indexed_items, self.highlights)
2573
+ self.draw_screen()
2576
2574
 
2577
2575
  if self.check_key("info", key, self.keys_dict):
2578
2576
  self.logger.info(f"key_function help")
@@ -2686,13 +2684,13 @@ class Picker:
2686
2684
  OptionPicker = Picker(self.stdscr, **info_data)
2687
2685
  s, o, f = OptionPicker.run()
2688
2686
 
2689
- self.draw_screen(self.indexed_items, self.highlights)
2687
+ self.draw_screen()
2690
2688
 
2691
2689
  elif self.check_key("exit", key, self.keys_dict):
2692
2690
  self.stdscr.clear()
2693
2691
  if len(self.loaded_files) <= 1:
2694
2692
  function_data = self.get_function_data()
2695
- function_data["last_key"] = key
2693
+ restore_terminal_settings(tty_fd, self.saved_terminal_state)
2696
2694
  return [], "", function_data
2697
2695
  else:
2698
2696
  del self.loaded_files[self.loaded_file_index]
@@ -2709,28 +2707,29 @@ class Picker:
2709
2707
  self.set_function_data({}, reset_absent_variables=True)
2710
2708
  self.load_file(self.loaded_file)
2711
2709
  self.loaded_file_index, self.loaded_file = idx, file
2712
- self.draw_screen(self.indexed_items, self.highlights)
2710
+ self.draw_screen()
2713
2711
 
2714
2712
  elif self.check_key("full_exit", key, self.keys_dict):
2715
2713
  close_curses(self.stdscr)
2714
+ restore_terminal_settings(tty_fd, self.saved_terminal_state)
2716
2715
  exit()
2717
2716
 
2718
2717
  elif self.check_key("settings_input", key, self.keys_dict):
2719
2718
  self.logger.info(f"Settings input")
2720
2719
  usrtxt = f"{self.user_settings.strip()} " if self.user_settings else ""
2721
- field_end_f = lambda: self.stdscr.getmaxyx()[1]-38 if self.show_footer else lambda: self.stdscr.getmaxyx()[1]-3
2722
- if self.show_footer and self.footer.height >= 2: field_end_f = lambda: self.stdscr.getmaxyx()[1]-38
2723
- else: field_end_f = lambda: self.stdscr.getmaxyx()[1]-3
2720
+ field_end_f = lambda: self.get_term_size()[1]-38 if self.show_footer else lambda: self.get_term_size()[1]-3
2721
+ if self.show_footer and self.footer.height >= 2: field_end_f = lambda: self.get_term_size()[1]-38
2722
+ else: field_end_f = lambda: self.get_term_size()[1]-3
2724
2723
  self.set_registers()
2725
2724
  usrtxt, return_val = input_field(
2726
2725
  self.stdscr,
2727
2726
  usrtxt=usrtxt,
2728
2727
  field_prefix=" Settings: ",
2729
2728
  x=lambda:2,
2730
- y=lambda: self.stdscr.getmaxyx()[0]-1,
2729
+ y=lambda: self.get_term_size()[0]-1,
2731
2730
  max_length=field_end_f,
2732
2731
  registers=self.registers,
2733
- refresh_screen_function=lambda: self.draw_screen(self.indexed_items, self.highlights),
2732
+ refresh_screen_function=lambda: self.draw_screen(),
2734
2733
  history=self.history_settings,
2735
2734
  path_auto_complete=True,
2736
2735
  formula_auto_complete=False,
@@ -2786,6 +2785,7 @@ class Picker:
2786
2785
 
2787
2786
  elif self.check_key("redo", key, self.keys_dict):
2788
2787
  self.redo()
2788
+
2789
2789
  # elif self.check_key("move_column_left", key, self.keys_dict):
2790
2790
  # tmp1 = self.column_indices[self.selected_column]
2791
2791
  # tmp2 = self.column_indices[(self.selected_column-1)%len(self.column_indices)]
@@ -2795,7 +2795,7 @@ class Picker:
2795
2795
  # # self.notification(self.stdscr, f"{str(self.column_indices)}, {tmp1}, {tmp2}")
2796
2796
  # self.initialise_variables()
2797
2797
  # 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)
2798
- # self.draw_screen(self.indexed_items, self.highlights)
2798
+ # self.draw_screen()
2799
2799
  # # self.move_column(direction=-1)
2800
2800
  #
2801
2801
  # elif self.check_key("move_column_right", key, self.keys_dict):
@@ -2805,7 +2805,7 @@ class Picker:
2805
2805
  # self.column_indices[(self.selected_column+1)%(len(self.column_indices))] = tmp1
2806
2806
  # self.selected_column = (self.selected_column+1)%len(self.column_indices)
2807
2807
  # self.initialise_variables()
2808
- # self.draw_screen(self.indexed_items, self.highlights)
2808
+ # self.draw_screen()
2809
2809
  # # self.move_column(direction=1)
2810
2810
 
2811
2811
  elif self.check_key("cursor_down", key, self.keys_dict):
@@ -2873,7 +2873,7 @@ class Picker:
2873
2873
  if new_pos < len(self.indexed_items):
2874
2874
  self.cursor_pos = new_pos
2875
2875
 
2876
- self.draw_screen(self.indexed_items, self.highlights)
2876
+ self.draw_screen()
2877
2877
 
2878
2878
  elif self.check_key("cursor_bottom", key, self.keys_dict):
2879
2879
  new_pos = len(self.indexed_items)-1
@@ -2882,19 +2882,19 @@ class Picker:
2882
2882
  else: break
2883
2883
  if new_pos < len(self.items) and new_pos >= 0:
2884
2884
  self.cursor_pos = new_pos
2885
- self.draw_screen(self.indexed_items, self.highlights)
2885
+ self.draw_screen()
2886
2886
  # current_row = items_per_page - 1
2887
2887
  # if current_page + 1 == (len(self.indexed_items) + items_per_page - 1) // items_per_page:
2888
2888
  #
2889
2889
  # current_row = (len(self.indexed_items) +items_per_page - 1) % items_per_page
2890
- # self.draw_screen(self.indexed_items, self.highlights)
2890
+ # self.draw_screen()
2891
2891
  elif self.check_key("enter", key, self.keys_dict):
2892
2892
  self.logger.info(f"key_function enter")
2893
2893
  # Print the selected indices if any, otherwise print the current index
2894
2894
  if self.is_selecting or self.is_deselecting: self.handle_visual_selection()
2895
2895
  if len(self.items) == 0:
2896
2896
  function_data = self.get_function_data()
2897
- function_data["last_key"] = key
2897
+ restore_terminal_settings(tty_fd, self.saved_terminal_state)
2898
2898
  return [], "", function_data
2899
2899
  selected_indices = get_selected_indices(self.selections)
2900
2900
  if not selected_indices and len(self.indexed_items):
@@ -2907,7 +2907,7 @@ class Picker:
2907
2907
  if self.option_functions[index] != None:
2908
2908
  options_sufficient, usrtxt = self.option_functions[index](
2909
2909
  stdscr=self.stdscr,
2910
- refresh_screen_function=lambda: self.draw_screen(self.indexed_items, self.highlights),
2910
+ refresh_screen_function=lambda: self.draw_screen(),
2911
2911
  )
2912
2912
  else:
2913
2913
  self.set_registers()
@@ -2923,7 +2923,7 @@ class Picker:
2923
2923
  self.stdscr.clear()
2924
2924
  self.stdscr.refresh()
2925
2925
  function_data = self.get_function_data()
2926
- function_data["last_key"] = key
2926
+ restore_terminal_settings(tty_fd, self.saved_terminal_state)
2927
2927
  return selected_indices, usrtxt, function_data
2928
2928
  elif self.check_key("page_down", key, self.keys_dict): # Next page
2929
2929
  self.cursor_pos = min(len(self.indexed_items) - 1, self.cursor_pos+self.items_per_page)
@@ -2940,7 +2940,7 @@ class Picker:
2940
2940
  self.stdscr.clear()
2941
2941
  self.stdscr.refresh()
2942
2942
 
2943
- self.draw_screen(self.indexed_items, self.highlights)
2943
+ self.draw_screen()
2944
2944
 
2945
2945
  elif self.check_key("cycle_sort_method", key, self.keys_dict):
2946
2946
  if self.sort_column == self.selected_column:
@@ -2968,7 +2968,7 @@ class Picker:
2968
2968
  if len(self.indexed_items) > 0:
2969
2969
  current_index = self.indexed_items[self.cursor_pos][0]
2970
2970
  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
2971
- self.draw_screen(self.indexed_items, self.highlights)
2971
+ self.draw_screen()
2972
2972
  self.cursor_pos = [row[0] for row in self.indexed_items].index(current_index)
2973
2973
  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]})")
2974
2974
  elif self.check_key("col_select", key, self.keys_dict):
@@ -3146,47 +3146,49 @@ class Picker:
3146
3146
 
3147
3147
  # elif self.check_key("increase_lines_per_page", key, self.keys_dict):
3148
3148
  # self.items_per_page += 1
3149
- # self.draw_screen(self.indexed_items, self.highlights)
3149
+ # self.draw_screen()
3150
3150
  # elif self.check_key("decrease_lines_per_page", key, self.keys_dict):
3151
3151
  # if self.items_per_page > 1:
3152
3152
  # self.items_per_page -= 1
3153
- # self.draw_screen(self.indexed_items, self.highlights)
3153
+ # self.draw_screen()
3154
3154
  elif self.check_key("decrease_column_width", key, self.keys_dict):
3155
3155
  self.logger.info(f"key_function decrease_column_width")
3156
3156
  if self.max_column_width > 10:
3157
3157
  self.max_column_width -= 10
3158
3158
  # 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)
3159
- self.draw_screen(self.indexed_items, self.highlights)
3159
+ self.draw_screen()
3160
3160
  elif self.check_key("increase_column_width", key, self.keys_dict):
3161
3161
  self.logger.info(f"key_function increase_column_width")
3162
3162
  if self.max_column_width < 1000:
3163
3163
  self.max_column_width += 10
3164
3164
  # 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)
3165
- self.draw_screen(self.indexed_items, self.highlights)
3165
+ self.draw_screen()
3166
3166
  elif self.check_key("visual_selection_toggle", key, self.keys_dict):
3167
3167
  self.logger.info(f"key_function visual_selection_toggle")
3168
3168
  self.handle_visual_selection()
3169
- self.draw_screen(self.indexed_items, self.highlights)
3169
+ self.draw_screen()
3170
3170
 
3171
3171
  elif self.check_key("visual_deselection_toggle", key, self.keys_dict):
3172
3172
  self.logger.info(f"key_function visual_deselection_toggle")
3173
3173
  self.handle_visual_selection(selecting=False)
3174
- self.draw_screen(self.indexed_items, self.highlights)
3174
+ self.draw_screen()
3175
3175
 
3176
3176
  elif key == curses.KEY_RESIZE: # Terminal resize signal
3177
3177
 
3178
3178
  self.calculate_section_sizes()
3179
3179
  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=self.rows_w, unicode_char_width=self.unicode_char_width)
3180
- self.draw_screen(self.indexed_items, self.highlights)
3180
+ self.stdscr.clear()
3181
+ self.stdscr.refresh()
3182
+ self.draw_screen()
3181
3183
 
3182
3184
 
3183
3185
  elif self.check_key("filter_input", key, self.keys_dict):
3184
3186
  self.logger.info(f"key_function filter_input")
3185
- self.draw_screen(self.indexed_items, self.highlights)
3187
+ self.draw_screen()
3186
3188
  usrtxt = f"{self.filter_query} " if self.filter_query else ""
3187
- field_end_f = lambda: self.stdscr.getmaxyx()[1]-38 if self.show_footer else lambda: self.stdscr.getmaxyx()[1]-3
3188
- if self.show_footer and self.footer.height >= 2: field_end_f = lambda: self.stdscr.getmaxyx()[1]-38
3189
- else: field_end_f = lambda: self.stdscr.getmaxyx()[1]-3
3189
+ field_end_f = lambda: self.get_term_size()[1]-38 if self.show_footer else lambda: self.get_term_size()[1]-3
3190
+ if self.show_footer and self.footer.height >= 2: field_end_f = lambda: self.get_term_size()[1]-38
3191
+ else: field_end_f = lambda: self.get_term_size()[1]-3
3190
3192
  self.set_registers()
3191
3193
  words = self.get_word_list()
3192
3194
  usrtxt, return_val = input_field(
@@ -3194,11 +3196,11 @@ class Picker:
3194
3196
  usrtxt=usrtxt,
3195
3197
  field_prefix=" Filter: ",
3196
3198
  x=lambda:2,
3197
- y=lambda: self.stdscr.getmaxyx()[0]-2,
3199
+ y=lambda: self.get_term_size()[0]-2,
3198
3200
  # max_length=field_end,
3199
3201
  max_length=field_end_f,
3200
3202
  registers=self.registers,
3201
- refresh_screen_function=lambda: self.draw_screen(self.indexed_items, self.highlights),
3203
+ refresh_screen_function=lambda: self.draw_screen(),
3202
3204
  history=self.history_filter_and_search,
3203
3205
  path_auto_complete=True,
3204
3206
  formula_auto_complete=False,
@@ -3227,11 +3229,11 @@ class Picker:
3227
3229
 
3228
3230
  elif self.check_key("search_input", key, self.keys_dict):
3229
3231
  self.logger.info(f"key_function search_input")
3230
- self.draw_screen(self.indexed_items, self.highlights)
3232
+ self.draw_screen()
3231
3233
  usrtxt = f"{self.search_query} " if self.search_query else ""
3232
- field_end_f = lambda: self.stdscr.getmaxyx()[1]-38 if self.show_footer else lambda: self.stdscr.getmaxyx()[1]-3
3233
- if self.show_footer and self.footer.height >= 3: field_end_f = lambda: self.stdscr.getmaxyx()[1]-38
3234
- else: field_end_f = lambda: self.stdscr.getmaxyx()[1]-3
3234
+ field_end_f = lambda: self.get_term_size()[1]-38 if self.show_footer else lambda: self.get_term_size()[1]-3
3235
+ if self.show_footer and self.footer.height >= 3: field_end_f = lambda: self.get_term_size()[1]-38
3236
+ else: field_end_f = lambda: self.get_term_size()[1]-3
3235
3237
  self.set_registers()
3236
3238
  words = self.get_word_list()
3237
3239
  usrtxt, return_val = input_field(
@@ -3239,10 +3241,10 @@ class Picker:
3239
3241
  usrtxt=usrtxt,
3240
3242
  field_prefix=" Search: ",
3241
3243
  x=lambda:2,
3242
- y=lambda: self.stdscr.getmaxyx()[0]-3,
3244
+ y=lambda: self.get_term_size()[0]-3,
3243
3245
  max_length=field_end_f,
3244
3246
  registers=self.registers,
3245
- refresh_screen_function=lambda: self.draw_screen(self.indexed_items, self.highlights),
3247
+ refresh_screen_function=lambda: self.draw_screen(),
3246
3248
  history=self.history_filter_and_search,
3247
3249
  path_auto_complete=True,
3248
3250
  formula_auto_complete=False,
@@ -3327,7 +3329,6 @@ class Picker:
3327
3329
  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
3328
3330
  elif self.cancel_is_back:
3329
3331
  function_data = self.get_function_data()
3330
- function_data["last_key"] = key
3331
3332
  return [], "escape", function_data
3332
3333
 
3333
3334
 
@@ -3336,14 +3337,14 @@ class Picker:
3336
3337
  # self.mode_index = 0
3337
3338
  # self.highlights = [highlight for highlight in self.highlights if "type" not in highlight or highlight["type"] != "search" ]
3338
3339
  # continue
3339
- self.draw_screen(self.indexed_items, self.highlights)
3340
+ self.draw_screen()
3340
3341
 
3341
3342
  elif self.check_key("opts_input", key, self.keys_dict):
3342
3343
  self.logger.info(f"key_function opts_input")
3343
3344
  usrtxt = f"{self.user_opts} " if self.user_opts else ""
3344
- field_end_f = lambda: self.stdscr.getmaxyx()[1]-38 if self.show_footer else lambda: self.stdscr.getmaxyx()[1]-3
3345
- if self.show_footer and self.footer.height >= 1: field_end_f = lambda: self.stdscr.getmaxyx()[1]-38
3346
- else: field_end_f = lambda: self.stdscr.getmaxyx()[1]-3
3345
+ field_end_f = lambda: self.get_term_size()[1]-38 if self.show_footer else lambda: self.get_term_size()[1]-3
3346
+ if self.show_footer and self.footer.height >= 1: field_end_f = lambda: self.get_term_size()[1]-38
3347
+ else: field_end_f = lambda: self.get_term_size()[1]-3
3347
3348
  self.set_registers()
3348
3349
  words = self.get_word_list()
3349
3350
  usrtxt, return_val = input_field(
@@ -3351,10 +3352,10 @@ class Picker:
3351
3352
  usrtxt=usrtxt,
3352
3353
  field_prefix=" Opts: ",
3353
3354
  x=lambda:2,
3354
- y=lambda: self.stdscr.getmaxyx()[0]-1,
3355
+ y=lambda: self.get_term_size()[0]-1,
3355
3356
  max_length=field_end_f,
3356
3357
  registers=self.registers,
3357
- refresh_screen_function=lambda: self.draw_screen(self.indexed_items, self.highlights),
3358
+ refresh_screen_function=lambda: self.draw_screen(),
3358
3359
  history=self.history_opts,
3359
3360
  path_auto_complete=True,
3360
3361
  formula_auto_complete=False,
@@ -3436,9 +3437,9 @@ class Picker:
3436
3437
  self.logger.info(f"key_function pipe_input")
3437
3438
  # usrtxt = "xargs -d '\n' -I{} "
3438
3439
  usrtxt = "xargs "
3439
- field_end_f = lambda: self.stdscr.getmaxyx()[1]-38 if self.show_footer else lambda: self.stdscr.getmaxyx()[1]-3
3440
- if self.show_footer and self.footer.height >= 2: field_end_f = lambda: self.stdscr.getmaxyx()[1]-38
3441
- else: field_end_f = lambda: self.stdscr.getmaxyx()[1]-3
3440
+ field_end_f = lambda: self.get_term_size()[1]-38 if self.show_footer else lambda: self.get_term_size()[1]-3
3441
+ if self.show_footer and self.footer.height >= 2: field_end_f = lambda: self.get_term_size()[1]-38
3442
+ else: field_end_f = lambda: self.get_term_size()[1]-3
3442
3443
  self.set_registers()
3443
3444
 
3444
3445
  # Get list of available shell commands
@@ -3454,11 +3455,11 @@ class Picker:
3454
3455
  usrtxt=usrtxt,
3455
3456
  field_prefix=" Command: ",
3456
3457
  x=lambda:2,
3457
- y=lambda: self.stdscr.getmaxyx()[0]-2,
3458
+ y=lambda: self.get_term_size()[0]-2,
3458
3459
  literal=True,
3459
3460
  max_length=field_end_f,
3460
3461
  registers=self.registers,
3461
- refresh_screen_function=lambda: self.draw_screen(self.indexed_items, self.highlights),
3462
+ refresh_screen_function=lambda: self.draw_screen(),
3462
3463
  history=self.history_pipes,
3463
3464
  path_auto_complete=True,
3464
3465
  formula_auto_complete=False,
@@ -3548,9 +3549,9 @@ class Picker:
3548
3549
  if len(self.indexed_items) > 0 and self.selected_column >=0 and self.editable_columns[self.selected_column]:
3549
3550
  current_val = self.indexed_items[self.cursor_pos][1][self.selected_column]
3550
3551
  usrtxt = f"{current_val}"
3551
- field_end_f = lambda: self.stdscr.getmaxyx()[1]-38 if self.show_footer else lambda: self.stdscr.getmaxyx()[1]-3
3552
- if self.show_footer and self.footer.height >= 2: field_end_f = lambda: self.stdscr.getmaxyx()[1]-38
3553
- else: field_end_f = lambda: self.stdscr.getmaxyx()[1]-3
3552
+ field_end_f = lambda: self.get_term_size()[1]-38 if self.show_footer else lambda: self.get_term_size()[1]-3
3553
+ if self.show_footer and self.footer.height >= 2: field_end_f = lambda: self.get_term_size()[1]-38
3554
+ else: field_end_f = lambda: self.get_term_size()[1]-3
3554
3555
  self.set_registers()
3555
3556
  words = self.get_word_list()
3556
3557
  usrtxt, return_val = input_field(
@@ -3558,10 +3559,10 @@ class Picker:
3558
3559
  usrtxt=usrtxt,
3559
3560
  field_prefix=" Edit value: ",
3560
3561
  x=lambda:2,
3561
- y=lambda: self.stdscr.getmaxyx()[0]-2,
3562
+ y=lambda: self.get_term_size()[0]-2,
3562
3563
  max_length=field_end_f,
3563
3564
  registers=self.registers,
3564
- refresh_screen_function=lambda: self.draw_screen(self.indexed_items, self.highlights),
3565
+ refresh_screen_function=lambda: self.draw_screen(),
3565
3566
  history = self.history_edits,
3566
3567
  path_auto_complete=True,
3567
3568
  formula_auto_complete=True,
@@ -3580,9 +3581,9 @@ class Picker:
3580
3581
  if len(self.indexed_items) > 0 and self.selected_column >=0 and self.editable_columns[self.selected_column]:
3581
3582
  current_val = self.indexed_items[self.cursor_pos][1][self.selected_column]
3582
3583
  usrtxt = f"{current_val}"
3583
- field_end_f = lambda: self.stdscr.getmaxyx()[1]-38 if self.show_footer else lambda: self.stdscr.getmaxyx()[1]-3
3584
- if self.show_footer and self.footer.height >= 2: field_end_f = lambda: self.stdscr.getmaxyx()[1]-38
3585
- else: field_end_f = lambda: self.stdscr.getmaxyx()[1]-3
3584
+ field_end_f = lambda: self.get_term_size()[1]-38 if self.show_footer else lambda: self.get_term_size()[1]-3
3585
+ if self.show_footer and self.footer.height >= 2: field_end_f = lambda: self.get_term_size()[1]-38
3586
+ else: field_end_f = lambda: self.get_term_size()[1]-3
3586
3587
  self.set_registers()
3587
3588
  words = self.get_word_list()
3588
3589
  usrtxt, return_val = input_field(
@@ -3590,10 +3591,10 @@ class Picker:
3590
3591
  usrtxt=usrtxt,
3591
3592
  field_prefix=" Edit value: ",
3592
3593
  x=lambda:2,
3593
- y=lambda: self.stdscr.getmaxyx()[0]-2,
3594
+ y=lambda: self.get_term_size()[0]-2,
3594
3595
  max_length=field_end_f,
3595
3596
  registers=self.registers,
3596
- refresh_screen_function=lambda: self.draw_screen(self.indexed_items, self.highlights),
3597
+ refresh_screen_function=lambda: self.draw_screen(),
3597
3598
  history = self.history_edits,
3598
3599
  path_auto_complete=True,
3599
3600
  formula_auto_complete=True,
@@ -3642,11 +3643,11 @@ class Picker:
3642
3643
  self.stdscr.clear()
3643
3644
  self.stdscr.refresh()
3644
3645
  self.initialise_variables()
3645
- self.draw_screen(self.indexed_items, self.highlights)
3646
+ self.draw_screen()
3646
3647
 
3647
3648
 
3648
3649
 
3649
- self.draw_screen(self.indexed_items, self.highlights, clear=clear_screen)
3650
+ self.draw_screen(clear=clear_screen)
3650
3651
 
3651
3652
 
3652
3653
 
@@ -3848,14 +3849,6 @@ def unrestrict_curses(stdscr: curses.window) -> None:
3848
3849
  def main() -> None:
3849
3850
  """ Main function when listpick is executed. Deals with command line arguments and starts a Picker. """
3850
3851
  args, function_data = parse_arguments()
3851
-
3852
- try:
3853
- if function_data["items"] == []:
3854
- function_data["items"] = test_items
3855
- function_data["highlights"] = test_highlights
3856
- function_data["header"] = test_header
3857
- except:
3858
- pass
3859
3852
 
3860
3853
  # function_data["colour_theme_number"] = 3
3861
3854
  function_data["highlights"] = [
@@ -41,9 +41,9 @@ def get_graph_string(x_vals, y_vals, width=50, height=20, title=None, x_label=No
41
41
  fig.ylabel = y_label
42
42
 
43
43
  # Generate the ASCII art of the graph
44
- ascii_art = str(fig.show())
44
+ graph_str = str(fig.show())
45
45
 
46
- return ascii_art
46
+ return graph_str
47
47
 
48
48
 
49
49
  def get_file_attributes(filename):
File without changes
@@ -16,27 +16,9 @@ from datetime import datetime
16
16
  import logging
17
17
 
18
18
  logger = logging.getLogger('picker_log')
19
- import select
20
- import tty
21
19
  from listpick.utils.user_input import get_char, open_tty
22
20
  from listpick.utils import keycodes
23
21
 
24
- # def open_tty():
25
- # """ Return a file descriptor for the tty that we are opening"""
26
- # tty_fd = os.open('/dev/tty', os.O_RDONLY)
27
- # tty.setraw(tty_fd)
28
- # return tty_fd
29
- #
30
- # def get_char(tty_fd, timeout: float = 0.2) -> int:
31
- # """ Get character from a tty_fd with a timeout. """
32
- # rlist, _, _ = select.select([tty_fd], [], [], timeout)
33
- # if rlist:
34
- # # key = ord(tty_fd.read(1))
35
- # key = ord(os.read(tty_fd, 1))
36
- # else:
37
- # key = -1
38
- # return key
39
-
40
22
  def input_field(
41
23
  stdscr: curses.window,
42
24
  usrtxt:str="",
@@ -126,7 +108,7 @@ def input_field(
126
108
  offscreen_x, offscreen_y = False, False
127
109
  orig_x, orig_y = x, y
128
110
 
129
- tty_fd = open_tty()
111
+ tty_fd, saved_terminal_state = open_tty()
130
112
 
131
113
  # Input field loop
132
114
  while True:
@@ -191,6 +191,7 @@ def generate_picker_data(
191
191
 
192
192
  num_workers = os.cpu_count()
193
193
  if num_workers in [None, -1]: num_workers = 4
194
+ if num_workers == None or num_workers < 1: num_workers = 1
194
195
  completed_cells = set()
195
196
 
196
197
  for _ in range(num_workers):
@@ -1,11 +1,17 @@
1
1
  from listpick.utils import keycodes
2
2
  import os, tty, select, curses
3
+ import termios
3
4
 
4
5
  def open_tty():
5
6
  """ Return a file descriptor for the tty that we are opening"""
6
7
  tty_fd = os.open('/dev/tty', os.O_RDONLY)
8
+ old_terminal_settings = termios.tcgetattr(tty_fd)
7
9
  tty.setraw(tty_fd)
8
- return tty_fd
10
+ return tty_fd, old_terminal_settings
11
+
12
+ def restore_terminal_settings(tty_fd, old_settings):
13
+ """ Restore the terminal to its previous state """
14
+ termios.tcsetattr(tty_fd, termios.TCSADRAIN, old_settings)
9
15
 
10
16
  def get_char(tty_fd, timeout: float = 0.2, secondary: bool = False) -> int:
11
17
  """ Get character from a tty_fd with a timeout. """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: listpick
3
- Version: 0.1.16.4
3
+ Version: 0.1.16.6
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,15 +1,16 @@
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=MDErM54fA_qvgMbo-IGovnUoDliBbaMSEGbHno-zhHA,203676
3
+ listpick/listpick_app.py,sha256=SenpQGK9E7bp21SLM2dMuWiTrhBoCGkeg8SRHPNGH-A,201481
4
4
  listpick/pane/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  listpick/pane/get_data.py,sha256=l12mHIb6qoZWIfW5zZZY8K8EqNcyIcRiHgtRaM2CVGs,2735
6
6
  listpick/pane/pane_functions.py,sha256=_dL9jHpd3sT0enL9H_bMcUsBlMELXdtP9dtKFSC2KPQ,5117
7
- listpick/pane/pane_utils.py,sha256=OEL4yBnBlIiHnT5bYtb3nQMn3WUR0vVH0gAGCtL1t0o,2539
7
+ listpick/pane/pane_utils.py,sha256=cnuzBH52wdWoKrHR6iMBF4N-uhwpXYpHDnrglk21pqg,2539
8
8
  listpick/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  listpick/ui/build_help.py,sha256=IpN4tX4U8ET3icRoTlF389VqVjVcPAon617vgstlPAc,10750
10
+ listpick/ui/draw_screen.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
11
  listpick/ui/footer.py,sha256=NcdH1uO_ma91m0qCczyQZ3zGrexfkiEnwDf5E4tHSMk,15089
11
12
  listpick/ui/help_screen.py,sha256=zbfGIgb-IXtATpl4_Sx7nPbsnRXZ7eiMYlCKGS9EFmw,5608
12
- listpick/ui/input_field.py,sha256=ylf3fiLXdAD4pueHWfzIrlwaRb9f5zm8f1UGkEPBxgM,30539
13
+ listpick/ui/input_field.py,sha256=scJjvmSS0QqeDbCky7_0Zgt35Aki7gezRJkrQROlLg4,30034
13
14
  listpick/ui/keys.py,sha256=1NCsOPFxhNuVPbO5vflcArNZ1jbBBerPQ3oZUAZDyPs,13682
14
15
  listpick/ui/picker_colours.py,sha256=FFsyny_q0mGO6u7B1n7anuReBtP7Jw6LrgX5ycN-MRM,13413
15
16
  listpick/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -18,7 +19,7 @@ listpick/utils/config.py,sha256=MEnAZg2Rhfl38XofEIN0uoVAOY7I0ftc79Evk3fOiVw,1654
18
19
  listpick/utils/dump.py,sha256=60YVIMNtBoYvWhmzfTJOsNGcetOvcCB3_T7yv-bYTPQ,3838
19
20
  listpick/utils/filtering.py,sha256=59_YIEYRV0ovnjF4iyuShq276FMAx5gBD9m3mE9IqJg,1237
20
21
  listpick/utils/generate_data.py,sha256=TCGwDrN49Xx33AdURpQRGi6Xi2uwjt96rEeWWYS8mFE,4649
21
- listpick/utils/generate_data_multithreaded.py,sha256=eWtv-gDdlTWwURKdg2cThrRI0I02JQNmQIr6q9GqtDc,6527
22
+ listpick/utils/generate_data_multithreaded.py,sha256=9TF-Z1qF3GDNFbe5K9Gf6EUj0UpruZTdKWHxz6jgGHY,6590
22
23
  listpick/utils/graphing.py,sha256=ugjAH8js_iH7hulg4SySxb_W_f8B6GhTaceN5i7DID4,6954
23
24
  listpick/utils/keycodes.py,sha256=ZGkw1-4szxPnP81wj80r92L6_neIOlBBjQltEieCwnk,2696
24
25
  listpick/utils/options_selectors.py,sha256=fQqTCAqRsrMhZwXUtsPBm47svkaUaeJqWsMW7Q4JTYY,3083
@@ -28,11 +29,11 @@ listpick/utils/search_and_filter_utils.py,sha256=XxGfkyDVXO9OAKcftPat8IReMTFIuTH
28
29
  listpick/utils/searching.py,sha256=Xk5UIqamNHL2L90z3ACB_Giqdpi9iRKoAJ6pKaqaD7Q,3093
29
30
  listpick/utils/sorting.py,sha256=WZZiVlVA3Zkcpwji3U5SNFlQ14zVEk3cZJtQirBkecQ,5329
30
31
  listpick/utils/table_to_list_of_lists.py,sha256=XBj7eGBDF15BRME-swnoXyOfZWxXCxrXp0pzsBfcJ5g,12224
31
- listpick/utils/user_input.py,sha256=oyJZPAwA7UGAclPhdPL44tKnPIVNHWhX-tZEnCdBKC0,4318
32
+ listpick/utils/user_input.py,sha256=L3ylI7nnuFM_TP1XKwpiKpxUSkNb2W5cr7mJjTmv_6E,4582
32
33
  listpick/utils/utils.py,sha256=nsR6orCBQy3rTXrCweq8cV-RzRVU15v3J9NclPeAOJk,13741
33
- listpick-0.1.16.4.dist-info/licenses/LICENSE.txt,sha256=2mP-MRHJptADDNE9VInMNg1tE-C6Qv93Z4CCQKrpg9w,1061
34
- listpick-0.1.16.4.dist-info/METADATA,sha256=VwWPk2nx7z_mnZJz8ips6nLYm0_YZcIxP6Y8KLegyIA,8128
35
- listpick-0.1.16.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
- listpick-0.1.16.4.dist-info/entry_points.txt,sha256=-QCf_BKIkUz35Y9nkYpjZWs2Qg0KfRna2PAs5DnF6BE,43
37
- listpick-0.1.16.4.dist-info/top_level.txt,sha256=5mtsGEz86rz3qQDe0D463gGjAfSp6A3EWg4J4AGYr-Q,9
38
- listpick-0.1.16.4.dist-info/RECORD,,
34
+ listpick-0.1.16.6.dist-info/licenses/LICENSE.txt,sha256=2mP-MRHJptADDNE9VInMNg1tE-C6Qv93Z4CCQKrpg9w,1061
35
+ listpick-0.1.16.6.dist-info/METADATA,sha256=q67Zxlt_QP9xQwlQfG07KEBULpHt2r6E_U3xeTAjp5c,8128
36
+ listpick-0.1.16.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
+ listpick-0.1.16.6.dist-info/entry_points.txt,sha256=-QCf_BKIkUz35Y9nkYpjZWs2Qg0KfRna2PAs5DnF6BE,43
38
+ listpick-0.1.16.6.dist-info/top_level.txt,sha256=5mtsGEz86rz3qQDe0D463gGjAfSp6A3EWg4J4AGYr-Q,9
39
+ listpick-0.1.16.6.dist-info/RECORD,,