listpick 0.1.14.4__tar.gz → 0.1.14.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. {listpick-0.1.14.4 → listpick-0.1.14.5}/CHANGELOG.md +1 -0
  2. {listpick-0.1.14.4/src/listpick.egg-info → listpick-0.1.14.5}/PKG-INFO +1 -1
  3. {listpick-0.1.14.4 → listpick-0.1.14.5}/setup.py +1 -1
  4. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/listpick_app.py +97 -13
  5. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/ui/input_field.py +47 -6
  6. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/ui/keys.py +4 -4
  7. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/utils/table_to_list_of_lists.py +111 -43
  8. {listpick-0.1.14.4 → listpick-0.1.14.5/src/listpick.egg-info}/PKG-INFO +1 -1
  9. {listpick-0.1.14.4 → listpick-0.1.14.5}/.gitignore +0 -0
  10. {listpick-0.1.14.4 → listpick-0.1.14.5}/LICENSE.txt +0 -0
  11. {listpick-0.1.14.4 → listpick-0.1.14.5}/README.md +0 -0
  12. {listpick-0.1.14.4 → listpick-0.1.14.5}/TODO.md +0 -0
  13. {listpick-0.1.14.4 → listpick-0.1.14.5}/assets/aria2tui_screenshot.png +0 -0
  14. {listpick-0.1.14.4 → listpick-0.1.14.5}/assets/file_compare.png +0 -0
  15. {listpick-0.1.14.4 → listpick-0.1.14.5}/assets/lpfman.png +0 -0
  16. {listpick-0.1.14.4 → listpick-0.1.14.5}/examples/data_generation/list_files.toml +0 -0
  17. {listpick-0.1.14.4 → listpick-0.1.14.5}/examples/data_generation/list_files_empty.toml +0 -0
  18. {listpick-0.1.14.4 → listpick-0.1.14.5}/examples/data_generation/video_duplicates.toml +0 -0
  19. {listpick-0.1.14.4 → listpick-0.1.14.5}/examples/data_generation/video_mediainfo.toml +0 -0
  20. {listpick-0.1.14.4 → listpick-0.1.14.5}/examples/input_files/polynomials.tsv +0 -0
  21. {listpick-0.1.14.4 → listpick-0.1.14.5}/examples/input_guides/gnuplot_graph.md +0 -0
  22. {listpick-0.1.14.4 → listpick-0.1.14.5}/examples/picker/auxiallary_files/2024-25_Premier_League.pkl +0 -0
  23. {listpick-0.1.14.4 → listpick-0.1.14.5}/examples/picker/footer_string_example.py +0 -0
  24. {listpick-0.1.14.4 → listpick-0.1.14.5}/examples/picker/picker_example.py +0 -0
  25. {listpick-0.1.14.4 → listpick-0.1.14.5}/examples/picker/template.py +0 -0
  26. {listpick-0.1.14.4 → listpick-0.1.14.5}/examples/picker/wikipedia_table.py +0 -0
  27. {listpick-0.1.14.4 → listpick-0.1.14.5}/listpick.py +0 -0
  28. {listpick-0.1.14.4 → listpick-0.1.14.5}/requirements.txt +0 -0
  29. {listpick-0.1.14.4 → listpick-0.1.14.5}/setup.cfg +0 -0
  30. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/__init__.py +0 -0
  31. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/__main__.py +0 -0
  32. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/ui/__init__.py +0 -0
  33. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/ui/build_help.py +0 -0
  34. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/ui/footer.py +0 -0
  35. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/ui/git-bugreport-2025-08-16-1438.txt +0 -0
  36. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/ui/help_screen.py +0 -0
  37. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/ui/pane_stuff.py +0 -0
  38. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/ui/picker_colours.py +0 -0
  39. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/utils/__init__.py +0 -0
  40. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/utils/clipboard_operations.py +0 -0
  41. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/utils/config.py +0 -0
  42. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/utils/dump.py +0 -0
  43. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/utils/filtering.py +0 -0
  44. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/utils/generate_data.py +0 -0
  45. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/utils/options_selectors.py +0 -0
  46. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/utils/paste_operations.py +0 -0
  47. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/utils/picker_log.py +0 -0
  48. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/utils/search_and_filter_utils.py +0 -0
  49. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/utils/searching.py +0 -0
  50. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/utils/sorting.py +0 -0
  51. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick/utils/utils.py +0 -0
  52. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick.egg-info/SOURCES.txt +0 -0
  53. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick.egg-info/dependency_links.txt +0 -0
  54. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick.egg-info/entry_points.txt +0 -0
  55. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick.egg-info/requires.txt +0 -0
  56. {listpick-0.1.14.4 → listpick-0.1.14.5}/src/listpick.egg-info/top_level.txt +0 -0
  57. {listpick-0.1.14.4 → listpick-0.1.14.5}/tests/kitty_control.sh +0 -0
  58. {listpick-0.1.14.4 → listpick-0.1.14.5}/tests/sorting_dates.csv +0 -0
@@ -7,6 +7,7 @@ Note that the changes between 0.1.11.0 and 1.1.12.0 are listed under 0.1.11
7
7
  - Added __sizeof__() function for the Picker class.
8
8
  - Fixed rows resizing twice when opening/switching between some files.
9
9
  - Added to settings: goto row, goto column
10
+ - NaN replaced with empty string when loading empty cells from xlsx or ods files.
10
11
 
11
12
  ## [0.1.14] 2025-08-20
12
13
  - Fixed bug when cells are centred vertically.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: listpick
3
- Version: 0.1.14.4
3
+ Version: 0.1.14.5
4
4
  Summary: Listpick is a powerful TUI data tool for creating TUI apps or viewing/comparing tabulated data.
5
5
  Home-page: https://github.com/grimandgreedy/listpick
6
6
  Author: Grim
@@ -16,7 +16,7 @@ with open("README.md", "r", encoding = "utf-8") as fh:
16
16
 
17
17
  setuptools.setup(
18
18
  name = "listpick",
19
- version = "0.1.14.4",
19
+ version = "0.1.14.5",
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.",
@@ -20,6 +20,8 @@ import json
20
20
  import threading
21
21
  import string
22
22
  import logging
23
+ import tty
24
+ import select
23
25
 
24
26
  from listpick.ui.picker_colours import get_colours, get_help_colours, get_notification_colours, get_theme_count, get_fallback_colours
25
27
  from listpick.utils.options_selectors import default_option_input, output_file_option_selector, default_option_selector
@@ -349,6 +351,65 @@ class Picker:
349
351
  if not attr_name.startswith('__') and not callable(getattr(self, attr_name)):
350
352
  size += sys.getsizeof(getattr(self, attr_name))
351
353
  return size
354
+
355
+ def set_config(self, path: str ="~/.config/listpick/config.toml"):
356
+ """ Set config from toml file. """
357
+ config = self.get_config(path)
358
+ self.logger.info(f"function: set_config()")
359
+ if "general" in config:
360
+ for key, val in config["general"].items():
361
+ self.logger.info(f"set_config: key={key}, val={val}.")
362
+ try:
363
+ setattr(self, key, val)
364
+ except Exception as e:
365
+ self.logger.error(f"set_config: key={key}, val={val}. {e}")
366
+
367
+
368
+ def get_config(self, path: str ="~/.config/listpick/config.toml") -> dict:
369
+ """ Get config from file. """
370
+ self.logger.info(f"function: get_config()")
371
+ import toml
372
+ if os.path.exists(os.path.expanduser(path)):
373
+ with open(os.path.expanduser(path), "r") as f:
374
+ config = toml.load(f)
375
+ return config
376
+ # full_config = self.get_default_config()
377
+ # default_path = "~/.config/listpick/config.toml"
378
+ #
379
+ # CONFIGPATH = default_path
380
+
381
+
382
+
383
+ # if "general" in config:
384
+ # for key in config["general"]:
385
+ # full_config["general"][key] = config["general"][key]
386
+ # if "appearance" in config:
387
+ # for key in config["appearance"]:
388
+ # full_config["appearance"][key] = config["appearance"][key]
389
+ #
390
+ # return full_config
391
+
392
+ def get_default_config(self) -> dict:
393
+ default_config = {
394
+ "general" : {
395
+ "url": "http://localhost",
396
+ "port": "6800",
397
+ "token": "",
398
+ "startupcmds": ["aria2c"],
399
+ "restartcmds": ["pkill aria2c && sleep 1 && aria2c"],
400
+ "ariaconfigpath": "~/.config/aria2/aria2.conf",
401
+ "paginate": False,
402
+ "refresh_timer": 2,
403
+ "global_stats_timer": 1,
404
+ "terminal_file_manager": "yazi",
405
+ "gui_file_manager": "kitty yazi",
406
+ "launch_command": "xdg-open",
407
+ },
408
+ "appearance":{
409
+ "theme": 0
410
+ }
411
+ }
412
+ return default_config
352
413
 
353
414
  def calculate_section_sizes(self):
354
415
  """
@@ -2179,10 +2240,14 @@ class Picker:
2179
2240
  function_data = self.get_function_data()
2180
2241
  return [], "", function_data
2181
2242
 
2182
- # Main loop
2243
+ # Open tty to accept input
2244
+ tty_fd = open_tty()
2183
2245
 
2246
+ # Main loop
2184
2247
  while True:
2185
- key = self.stdscr.getch()
2248
+ # key = self.stdscr.getch()
2249
+
2250
+ key = get_char(tty_fd, timeout=0.2)
2186
2251
  if key != -1:
2187
2252
  self.logger.info(f"key={key}")
2188
2253
  h, w = self.stdscr.getmaxyx()
@@ -2421,7 +2486,7 @@ class Picker:
2421
2486
  formula_auto_complete=False,
2422
2487
  function_auto_complete=False,
2423
2488
  word_auto_complete=True,
2424
- auto_complete_words=["ft", "ct", "cv"]
2489
+ auto_complete_words=["ft", "ct", "cv"],
2425
2490
  )
2426
2491
  if return_val:
2427
2492
  self.user_settings = usrtxt
@@ -3505,6 +3570,24 @@ def unrestrict_curses(stdscr: curses.window) -> None:
3505
3570
  curses.raw() # Disable control keys (ctrl-c, ctrl-s, ctrl-q, etc.)
3506
3571
  curses.curs_set(False)
3507
3572
 
3573
+
3574
+ def open_tty():
3575
+ """ Return a file descriptor for the tty that we are opening"""
3576
+ tty_fd = os.open('/dev/tty', os.O_RDONLY)
3577
+ tty.setraw(tty_fd)
3578
+ return tty_fd
3579
+
3580
+ def get_char(tty_fd, timeout: float = 0.2) -> int:
3581
+ """ Get character from a tty_fd with a timeout. """
3582
+ rlist, _, _ = select.select([tty_fd], [], [], timeout)
3583
+ if rlist:
3584
+ # key = ord(tty_fd.read(1))
3585
+ key = ord(os.read(tty_fd, 1))
3586
+ # os.system(f"notify-send { key }")
3587
+ else:
3588
+ key = -1
3589
+ return key
3590
+
3508
3591
  def main() -> None:
3509
3592
  """ Main function when listpick is executed. Deals with command line arguments and starts a Picker. """
3510
3593
  args, function_data = parse_arguments()
@@ -3540,16 +3623,16 @@ def main() -> None:
3540
3623
  "color": 8,
3541
3624
  }
3542
3625
  ]
3543
- function_data["cell_cursor"] = True
3544
- function_data["display_modes"] = True
3545
- function_data["centre_in_cols"] = True
3546
- function_data["show_row_header"] = True
3547
- function_data["keys_dict"] = picker_keys
3548
- function_data["id_column"] = -1
3549
- function_data["track_entries_upon_refresh"] = True
3550
- function_data["centre_in_terminal_vertical"] = True
3551
- function_data["highlight_full_row"] = True
3552
- function_data["pin_cursor"] = True
3626
+ # function_data["cell_cursor"] = True
3627
+ # function_data["display_modes"] = True
3628
+ # function_data["centre_in_cols"] = True
3629
+ # function_data["show_row_header"] = True
3630
+ # function_data["keys_dict"] = picker_keys
3631
+ # function_data["id_column"] = -1
3632
+ # function_data["track_entries_upon_refresh"] = True
3633
+ # function_data["centre_in_terminal_vertical"] = True
3634
+ # function_data["highlight_full_row"] = True
3635
+ # function_data["pin_cursor"] = True
3553
3636
  # function_data["display_infobox"] = True
3554
3637
  # function_data["infobox_items"] = [["1"], ["2"], ["3"]]
3555
3638
  # function_data["infobox_title"] = "Title"
@@ -3572,6 +3655,7 @@ def main() -> None:
3572
3655
 
3573
3656
  # app = Picker(stdscr, **function_data)
3574
3657
  app = Picker(stdscr)
3658
+ app.set_config("~/.config/listpick/config.toml")
3575
3659
  app.set_function_data(function_data)
3576
3660
  app.splash_screen("Listpick is loading your data...")
3577
3661
  app.load_input_history("~/.config/listpick/cmdhist.json")
@@ -16,7 +16,26 @@ from datetime import datetime
16
16
  import logging
17
17
 
18
18
  logger = logging.getLogger('picker_log')
19
-
19
+ import select
20
+ import tty
21
+
22
+ def open_tty():
23
+ """ Return a file descriptor for the tty that we are opening"""
24
+ tty_fd = os.open('/dev/tty', os.O_RDONLY)
25
+ tty.setraw(tty_fd)
26
+ return tty_fd
27
+
28
+ def get_char(tty_fd, timeout: float = 0.2) -> int:
29
+ """ Get character from a tty_fd with a timeout. """
30
+ rlist, _, _ = select.select([tty_fd], [], [], timeout)
31
+ if rlist:
32
+ # key = ord(tty_fd.read(1))
33
+ key = ord(os.read(tty_fd, 1))
34
+ # os.system(f"notify-send { key }")
35
+ else:
36
+ key = -1
37
+ return key
38
+
20
39
  def input_field(
21
40
  stdscr: curses.window,
22
41
  usrtxt:str="",
@@ -106,6 +125,10 @@ def input_field(
106
125
  offscreen_x, offscreen_y = False, False
107
126
  orig_x, orig_y = x, y
108
127
 
128
+ # tty_fd = open('/dev/tty')
129
+ # tty_fd = os.open('/dev/tty', os.O_RDONLY)
130
+ # tty.setraw(tty_fd)
131
+ tty_fd = open_tty()
109
132
  # Input field loop
110
133
  while True:
111
134
 
@@ -131,7 +154,7 @@ def input_field(
131
154
 
132
155
  # Clear background to end of the input field
133
156
  stdscr.addstr(field_y, x(), " "*(max_field_length), curses.color_pair(colours_start+colour_pair_bg))
134
- stdscr.refresh()
157
+ # stdscr.refresh()
135
158
 
136
159
  if literal:
137
160
  field_string_length = len(repr(usrtxt)) + len(field_prefix)
@@ -206,12 +229,30 @@ def input_field(
206
229
  pass
207
230
 
208
231
 
209
- key = stdscr.getch()
232
+ stdscr.refresh()
233
+ # timeout = 0.05
234
+ # rlist, _, _ = select.select([tty_fd], [], [], timeout)
235
+ # if rlist:
236
+ # # key = ord(tty_fd.read(1))
237
+ # key = ord(os.read(tty_fd, 1))
238
+ # os.system(f"notify-send { key }")
239
+ # else:
240
+ # key = -1
241
+ key = get_char(tty_fd, timeout=0.5)
242
+ # key = ord(tty.read(1))
243
+ # key = stdscr.getch()
210
244
 
211
245
  if key in [27, 7]: # ESC/ALT key or Ctrl+g
212
246
  # For Alt-key combinations: set nodelay and get the second key
213
- stdscr.nodelay(True)
214
- key2 = stdscr.getch()
247
+ # stdscr.nodelay(True)
248
+ # key2 = stdscr.getch()
249
+ # rlist, _, _ = select.select([tty_fd], [], [], timeout)
250
+ # if rlist:
251
+ # key2 = ord(os.read(tty_fd, 1))
252
+ # os.system(f"notify-send 'metakey { key }'")
253
+ # else:
254
+ # key2 = -1
255
+ key2 = get_char(tty_fd, timeout=0.05)
215
256
 
216
257
  if key2 == -1: # ESCAPE key (no key-combination)
217
258
  stdscr.nodelay(False)
@@ -311,7 +352,7 @@ def input_field(
311
352
  curses.endwin()
312
353
  exit()
313
354
 
314
- elif key == 10: # Enter/return key
355
+ elif key in [10, 13]: # Enter/return key
315
356
  # Return
316
357
  return usrtxt, True
317
358
 
@@ -32,7 +32,7 @@ picker_keys = {
32
32
  "select_none": [ord('M'), 18], # Ctrl-r
33
33
  "visual_selection_toggle": [ord('v')],
34
34
  "visual_deselection_toggle": [ord('V')],
35
- "enter": [ord('\n'), curses.KEY_ENTER],
35
+ "enter": [ord('\n'), curses.KEY_ENTER, 13],
36
36
  "redraw_screen": [12], # Ctrl-l
37
37
  "cycle_sort_method": [ord('s')],
38
38
  "cycle_sort_method_reverse": [ord('S')],
@@ -152,7 +152,7 @@ menu_keys = {
152
152
  "cursor_top": [ord('g'), curses.KEY_HOME],
153
153
  "five_up": [ord('K')],
154
154
  "five_down": [ord('J')],
155
- "enter": [ord('\n'), curses.KEY_ENTER, ord('l')],
155
+ "enter": [ord('\n'), curses.KEY_ENTER, ord('l'), 13],
156
156
  "redraw_screen": [12], # Ctrl-l
157
157
  "filter_input": [ord('f')],
158
158
  "search_input": [ord('/')],
@@ -183,7 +183,7 @@ options_keys = {
183
183
  "select_none": [ord('M'), 18], # Ctrl-r
184
184
  "visual_selection_toggle": [ord('v')],
185
185
  "visual_deselection_toggle": [ord('V')],
186
- "enter": [ord('\n'), curses.KEY_ENTER, ord('l')],
186
+ "enter": [ord('\n'), curses.KEY_ENTER, ord('l'), 13],
187
187
  "redraw_screen": [12], # Ctrl-l
188
188
  "cycle_sort_method": [ord('s')],
189
189
  "cycle_sort_method_reverse": [ord('S')],
@@ -213,7 +213,7 @@ edit_menu_keys = {
213
213
  "cursor_top": [ord('g'), curses.KEY_HOME],
214
214
  "five_up": [ord('K')],
215
215
  "five_down": [ord('J')],
216
- "enter": [ord('\n'), curses.KEY_ENTER],
216
+ "enter": [ord('\n'), curses.KEY_ENTER, 13],
217
217
  "redraw_screen": [12], # Ctrl-l
218
218
  "cycle_sort_method": [ord('s')],
219
219
  "cycle_sort_method_reverse": [ord('S')],
@@ -36,6 +36,102 @@ def strip_whitespace(item: Iterable) -> Iterable:
36
36
  return item
37
37
 
38
38
 
39
+ def xlsx_to_list(file_name: str, sheet_number:int = 0, extract_formulae: bool = False):
40
+ import pandas as pd
41
+ from openpyxl import load_workbook
42
+ # wb = load_workbook(filename=input_arg, read_only=True)
43
+ # values or formulae
44
+ if not os.path.exists(file_name):
45
+ return [], [], []
46
+ wb = load_workbook(filename=file_name, read_only=True, data_only=not extract_formulae)
47
+
48
+ if not isinstance(sheet_number, int): sheet_number = 0
49
+ sheet_number = max(0, min(sheet_number, len(wb.sheetnames)-1))
50
+ ws = wb.worksheets[sheet_number]
51
+
52
+ # Read data and formulas from the sheet
53
+ table_data = []
54
+ # table_data = [[cell for cell in row] for row in ws.iter_rows(min_row=1, values_only=False)]
55
+ # table_data = [[cell.value for cell in row] for row in ws.iter_rows(min_row=1, values_only=False)]
56
+ table_data = [[cell if cell != None else "" for cell in row] for row in ws.iter_rows(min_row=1, values_only=True)]
57
+ header = []
58
+ # header = [cell for cell in list(ws.iter_rows(values_only=True))[0]] # Assuming the first row is the header
59
+ header = table_data[0]
60
+ table_data = table_data[1:]
61
+ #
62
+ # for row in ws.iter_rows(min_row=2, values_only=True): # Skip the header row
63
+ # row_data = []
64
+ # for cell in row:
65
+ # if isinstance(cell, str) and '=' in cell: # Check if it's a formula
66
+ # row_data.append(cell)
67
+ # else:
68
+ # row_data.append(str(cell))
69
+ # table_data.append(row_data)
70
+
71
+ return table_data, header, wb.sheetnames
72
+
73
+ def ods_to_list(filename: str, sheet_number: int = 0, extract_formulas: bool = False, first_row_is_header: bool = True):
74
+ from odf.opendocument import load
75
+ from odf import table, text
76
+
77
+ from odf.namespaces import TABLENS
78
+ # Load the ODS file
79
+ doc = load(filename)
80
+
81
+ sheets = doc.spreadsheet.getElementsByType(table.Table)
82
+ sheet_names = [s.attributes.get((TABLENS, 'name')) for s in sheets]
83
+
84
+
85
+ # Get the sheet by index
86
+ sheet = doc.spreadsheet.getElementsByType(table.Table)[sheet_number]
87
+
88
+ data = []
89
+ for row in sheet.getElementsByType(table.TableRow):
90
+ row_data = []
91
+ for cell in row.getElementsByType(table.TableCell):
92
+ if extract_formulas:
93
+ formula = cell.attributes.get((TABLENS, 'formula'))
94
+ if formula is not None:
95
+ row_data.append(formula)
96
+ continue # Skip extracting value if formula found
97
+
98
+ # Extract value (as text) from <text:p> elements
99
+ cell_text = ""
100
+ for p in cell.getElementsByType(text.P):
101
+ cell_text += str(p.firstChild) if p.firstChild is not None else ""
102
+ row_data.append(cell_text)
103
+ data.append(row_data)
104
+ if first_row_is_header and len(data) > 0:
105
+ header = data[0]
106
+ data = data[1:]
107
+ else:
108
+ header = []
109
+
110
+ return data, header, sheet_names
111
+
112
+ def ods_to_list_old(file_name: str, sheet_number:int = 0, extract_formulae: bool = False):
113
+ try:
114
+ import pandas as pd
115
+ ef = pd.ExcelFile(file_name)
116
+ sheets = ef.sheet_names
117
+ sheet_number = max(0, min(sheet_number, len(sheets)-1))
118
+ df = pd.read_excel(file_name, engine='odf', sheet_name=sheet_number)
119
+ # if sheet_number < len(sheets):
120
+ # df = pd.read_excel(input_arg, engine='odf', sheet_name=sheet_number)
121
+ # else:
122
+ # df = pd.read_excel(input_arg, engine='odf')
123
+ table_data = df.values.tolist()
124
+ table_data = [[x if not pd.isna(x) else "" for x in row] for row in table_data]
125
+
126
+ try:
127
+ header = list(df.columns)
128
+ except:
129
+ header = []
130
+ return table_data, header, sheets
131
+ except Exception as e:
132
+ print(f"Error loading ODS file: {e}")
133
+ return [], [], []
134
+
39
135
 
40
136
  def table_to_list(
41
137
 
@@ -80,7 +176,17 @@ def table_to_list(
80
176
  reader = csv.reader(f, skipinitialspace=True)
81
177
  return [row for row in reader]
82
178
 
83
- if file_type == 'csv' or delimiter in [',']:
179
+ if input_arg == '--stdin':
180
+ os.system(f"notify-send stdin")
181
+ input_data = sys.stdin.read()
182
+ elif input_arg == '--stdin2':
183
+ os.system(f"notify-send stdin2")
184
+ input_count = int(sys.stdin.readline())
185
+ input_data = "\n".join([sys.stdin.readline() for i in range(input_count)])
186
+ sys.stdin.flush()
187
+ # sys.stdin.close()
188
+ # sys.stdin = open('/dev/tty', 'r')
189
+ elif file_type == 'csv' or delimiter in [',']:
84
190
  try:
85
191
  if input_arg == '--stdin':
86
192
  input_data = sys.stdin.read()
@@ -141,45 +247,12 @@ def table_to_list(
141
247
  return [], [], []
142
248
 
143
249
  elif file_type == 'xlsx':
144
- import pandas as pd
145
- ef = pd.ExcelFile(input_arg)
146
- sheets = ef.sheet_names
147
- sheet_number = min(0, max(sheet_number, len(sheets)-1))
148
- df = pd.read_excel(input_arg, engine='odf', sheet_name=sheet_number)
149
- # if sheet_number < len(sheets):
150
- # df = pd.read_excel(input_arg, sheet_name=sheet_number)
151
- # else:
152
- # df = pd.read_excel(input_arg)
153
- table_data = df.values.tolist()
154
- table_data = [[x if not pd.isna(x) else "" for x in row] for row in table_data]
155
- try:
156
- header = list(df.columns)
157
- except:
158
- header = []
159
- return table_data, header, sheets
250
+ extract_formulae = False
251
+ return xlsx_to_list(input_arg, sheet_number, extract_formulae)
160
252
 
161
253
  elif file_type == 'ods':
162
- try:
163
- import pandas as pd
164
- ef = pd.ExcelFile(input_arg)
165
- sheets = ef.sheet_names
166
- sheet_number = min(0, max(sheet_number, len(sheets)-1))
167
- df = pd.read_excel(input_arg, engine='odf', sheet_name=sheet_number)
168
- # if sheet_number < len(sheets):
169
- # df = pd.read_excel(input_arg, engine='odf', sheet_name=sheet_number)
170
- # else:
171
- # df = pd.read_excel(input_arg, engine='odf')
172
- table_data = df.values.tolist()
173
- table_data = [[x if not pd.isna(x) else "" for x in row] for row in table_data]
174
-
175
- try:
176
- header = list(df.columns)
177
- except:
178
- header = []
179
- return table_data, header, sheets
180
- except Exception as e:
181
- print(f"Error loading ODS file: {e}")
182
- return [], [], []
254
+ extract_formulae = False
255
+ return ods_to_list(input_arg, sheet_number, extract_formulae)
183
256
  elif file_type == 'pkl':
184
257
  with open(os.path.expandvars(os.path.expanduser(input_arg)), 'rb') as f:
185
258
  loaded_data = pickle.load(f)
@@ -187,11 +260,6 @@ def table_to_list(
187
260
  header = loaded_data["header"] if "header" in loaded_data else []
188
261
  return items, header, []
189
262
 
190
- if input_arg == '--stdin':
191
- input_data = sys.stdin.read()
192
- elif input_arg == '--stdin2':
193
- input_count = int(sys.stdin.readline())
194
- input_data = "\n".join([sys.stdin.readline() for i in range(input_count)])
195
263
  else:
196
264
  input_data = read_file_content(input_arg)
197
265
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: listpick
3
- Version: 0.1.14.4
3
+ Version: 0.1.14.5
4
4
  Summary: Listpick is a powerful TUI data tool for creating TUI apps or viewing/comparing tabulated data.
5
5
  Home-page: https://github.com/grimandgreedy/listpick
6
6
  Author: Grim
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes