listpick 0.1.14.1__tar.gz → 0.1.14.3__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.1 → listpick-0.1.14.3}/CHANGELOG.md +4 -0
  2. {listpick-0.1.14.1/src/listpick.egg-info → listpick-0.1.14.3}/PKG-INFO +1 -1
  3. {listpick-0.1.14.1 → listpick-0.1.14.3}/TODO.md +4 -0
  4. listpick-0.1.14.3/examples/data_generation/list_files.toml +23 -0
  5. listpick-0.1.14.3/examples/data_generation/list_files_empty.toml +22 -0
  6. listpick-0.1.14.3/examples/data_generation/video_duplicates.toml +36 -0
  7. listpick-0.1.14.3/examples/data_generation/video_mediainfo.toml +32 -0
  8. listpick-0.1.14.3/examples/input_files/polynomials.tsv +31 -0
  9. listpick-0.1.14.3/examples/input_guides/gnuplot_graph.md +13 -0
  10. listpick-0.1.14.3/examples/picker/auxiallary_files/2024-25_Premier_League.pkl +0 -0
  11. listpick-0.1.14.3/examples/picker/footer_string_example.py +30 -0
  12. listpick-0.1.14.3/examples/picker/picker_example.py +54 -0
  13. listpick-0.1.14.3/examples/picker/template.py +28 -0
  14. listpick-0.1.14.3/examples/picker/wikipedia_table.py +78 -0
  15. {listpick-0.1.14.1 → listpick-0.1.14.3}/setup.py +1 -1
  16. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/listpick_app.py +111 -72
  17. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/build_help.py +3 -0
  18. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/footer.py +51 -35
  19. listpick-0.1.14.3/src/listpick/ui/git-bugreport-2025-08-16-1438.txt +37 -0
  20. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/keys.py +4 -2
  21. {listpick-0.1.14.1 → listpick-0.1.14.3/src/listpick.egg-info}/PKG-INFO +1 -1
  22. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick.egg-info/SOURCES.txt +12 -0
  23. {listpick-0.1.14.1 → listpick-0.1.14.3}/.gitignore +0 -0
  24. {listpick-0.1.14.1 → listpick-0.1.14.3}/LICENSE.txt +0 -0
  25. {listpick-0.1.14.1 → listpick-0.1.14.3}/README.md +0 -0
  26. {listpick-0.1.14.1 → listpick-0.1.14.3}/assets/aria2tui_screenshot.png +0 -0
  27. {listpick-0.1.14.1 → listpick-0.1.14.3}/assets/file_compare.png +0 -0
  28. {listpick-0.1.14.1 → listpick-0.1.14.3}/assets/lpfman.png +0 -0
  29. {listpick-0.1.14.1 → listpick-0.1.14.3}/listpick.py +0 -0
  30. {listpick-0.1.14.1 → listpick-0.1.14.3}/requirements.txt +0 -0
  31. {listpick-0.1.14.1 → listpick-0.1.14.3}/setup.cfg +0 -0
  32. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/__init__.py +0 -0
  33. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/__main__.py +0 -0
  34. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/__init__.py +0 -0
  35. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/help_screen.py +0 -0
  36. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/input_field.py +0 -0
  37. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/pane_stuff.py +0 -0
  38. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/picker_colours.py +0 -0
  39. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/__init__.py +0 -0
  40. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/clipboard_operations.py +0 -0
  41. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/config.py +0 -0
  42. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/dump.py +0 -0
  43. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/filtering.py +0 -0
  44. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/generate_data.py +0 -0
  45. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/options_selectors.py +0 -0
  46. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/paste_operations.py +0 -0
  47. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/picker_log.py +0 -0
  48. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/search_and_filter_utils.py +0 -0
  49. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/searching.py +0 -0
  50. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/sorting.py +0 -0
  51. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/table_to_list_of_lists.py +0 -0
  52. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/utils.py +0 -0
  53. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick.egg-info/dependency_links.txt +0 -0
  54. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick.egg-info/entry_points.txt +0 -0
  55. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick.egg-info/requires.txt +0 -0
  56. {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick.egg-info/top_level.txt +0 -0
  57. {listpick-0.1.14.1 → listpick-0.1.14.3}/tests/kitty_control.sh +0 -0
  58. {listpick-0.1.14.1 → listpick-0.1.14.3}/tests/sorting_dates.csv +0 -0
@@ -3,6 +3,10 @@ Note that the changes between 0.1.11.0 and 1.1.12.0 are listed under 0.1.11
3
3
 
4
4
  ## [0.1.15] 2025-??-??
5
5
  - Added info screen to display all information on the running Picker.
6
+ - Added keys for file_next and file_prev
7
+ - Added __sizeof__() function for the Picker class.
8
+ - Fixed rows resizing twice when opening/switching between some files.
9
+ - Added to settings: goto row, goto column
6
10
 
7
11
  ## [0.1.14] 2025-08-20
8
12
  - 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.1
3
+ Version: 0.1.14.3
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
@@ -11,6 +11,8 @@ ASAP
11
11
  > - [ ] While being displayed.
12
12
  > - [ ] Add keys for next page, next sheet, info
13
13
  > - [ ] Sort out what to do when the width of the columns is less than the terminal.
14
+ > - [ ] Sheet states remain the same when switching files.
15
+ > - [ ] nan in xlsx and ods files.
14
16
 
15
17
 
16
18
 
@@ -348,6 +350,8 @@ ASAP
348
350
  > - [x] Pink flash when loading. Likely due to colour redefinitions before picker actually loads.
349
351
  > - [x] Fixed. Created splashscreen class function which will be displayed after the colours are defined.
350
352
  > - [ ] If the longest string in a column is the header string and show_header=False, then get_column_widths still calculates based on the header string length.
353
+ > - [x] Rows sometimes adjust position a second time after switching files.
354
+ > - [x] Was due to the height of the footer being set only at the end of the Footer.draw() method. Created a new Footer.adjust_sizes() method which is run at the start of the draw_screen() loop.
351
355
 
352
356
 
353
357
 
@@ -0,0 +1,23 @@
1
+ #
2
+ # list_files.toml
3
+ # Generate list of files along with an empty column (invalid directory).
4
+ #
5
+ # Author: GrimAndGreedy
6
+ # License: MIT
7
+
8
+ [environment]
9
+ # cwd="~/"
10
+ cwd="~/Downloads/new/"
11
+
12
+ [data]
13
+ files_command = "eza -1 --no-quotes -a"
14
+
15
+ commands = [
16
+ """eza -1 --no-quotes -a""",
17
+ """eza -1 /nosuchdirectory""",
18
+ ]
19
+
20
+ header = [
21
+ "file",
22
+ "empty column"
23
+ ]
@@ -0,0 +1,22 @@
1
+ #
2
+ # list_files_empty.toml
3
+ # Generate list of files for non-existent files--empty picker.
4
+ #
5
+ # Author: GrimAndGreedy
6
+ # License: MIT
7
+
8
+ [environment]
9
+ cwd="~/Videos"
10
+
11
+ [data]
12
+ files_command = "eza -1 --no-quotes | grep zzz"
13
+
14
+ commands = [
15
+ """eza -1 --no-quotes | grep zzz""",
16
+ """eza -1 /nosuchdirectory""",
17
+ ]
18
+
19
+ header = [
20
+ "file",
21
+ "empty column"
22
+ ]
@@ -0,0 +1,36 @@
1
+ #
2
+ # video_duplicates.toml
3
+ # Generate list of mp4 files along with their: sha1, duration, width, height, and size.
4
+ #
5
+ # Author: GrimAndGreedy
6
+ # License: MIT
7
+
8
+
9
+ [environment]
10
+ cwd="~/Downloads/new/creators/ashla/"
11
+ # cwd="~/Videos/"
12
+
13
+ [data]
14
+ files_command = "eza -1 --no-quotes | grep -E mp4$"
15
+
16
+ commands = [
17
+ """eza -1 --no-quotes | grep -E mp4$""",
18
+ # """sha1sum {} | awk '{{print $1}}'""",
19
+ """ffprobe -show_entries format=duration -v quiet -of csv="p=0" -i {}""",
20
+ """ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=s=x:p=0 {}""",
21
+ """ffprobe -v error -select_streams v:0 -show_entries stream=height -of csv=s=x:p=0 {}""",
22
+ """du -hs {} | awk '{{ print $1 }}'"""
23
+ ]
24
+
25
+ header = [
26
+ "file",
27
+ # "sha1",
28
+ "duration",
29
+ "width",
30
+ "height",
31
+ "size",
32
+ ]
33
+
34
+ # run = [
35
+ # "mpv",
36
+ # ]
@@ -0,0 +1,32 @@
1
+ #
2
+ # video_mediainfo.toml
3
+ # Generate mediainfo for mp4 files in a directory
4
+ #
5
+ # Author: GrimAndGreedy
6
+ # License: MIT
7
+
8
+ [environment]
9
+ cwd="~/Videos"
10
+
11
+ [data]
12
+ files_command = "eza -1 --no-quotes | grep mp4"
13
+
14
+ commands = [
15
+ """eza -1 --no-quotes | grep mp4""",
16
+ """mediainfo {} | grep -i format | head -n 1 | awk -F ':' '{{print $2}}'""",
17
+ """mediainfo {} | grep -i height | head -n 1 | awk -F ':' '{{print $2}}'""",
18
+ """mediainfo {} | grep -i width | head -n 1 | awk -F ':' '{{print $2}}'""",
19
+ """mediainfo {} | grep -i duration | head -n 1 | awk -F ':' '{{print $2}}'""",
20
+ """mediainfo {} | grep -i 'bit rate' | head -n 1 | awk -F ':' '{{print $2}}'""",
21
+ """mediainfo {} | grep -i 'frame rate' | head -n 1 | awk -F ':' '{{print $2}}'""",
22
+ ]
23
+
24
+ header = [
25
+ "file",
26
+ "format",
27
+ "height",
28
+ "width",
29
+ "duration",
30
+ "bitrate",
31
+ "framerate",
32
+ ]
@@ -0,0 +1,31 @@
1
+ 0 0 0
2
+ 1 1 1
3
+ 2 4 8
4
+ 3 9 27
5
+ 4 16 64
6
+ 5 25 125
7
+ 6 36 216
8
+ 7 49 343
9
+ 8 64 512
10
+ 9 81 729
11
+ 10 100 1000
12
+ 11 121 1331
13
+ 12 144 1728
14
+ 13 169 2197
15
+ 14 196 2744
16
+ 15 225 3375
17
+ 16 256 4096
18
+ 17 289 4913
19
+ 18 324 5832
20
+ 19 361 6859
21
+ 20 400 8000
22
+ 21 441 9261
23
+ 22 484 10648
24
+ 23 529 12167
25
+ 24 576 13824
26
+ 25 625 15625
27
+ 26 676 17576
28
+ 27 729 19683
29
+ 28 784 21952
30
+ 29 841 24389
31
+ 30 900 27000
@@ -0,0 +1,13 @@
1
+ # Create a graph in a Picker using gnuplot
2
+
3
+ Ensure that gnuplot is installed and then run:
4
+
5
+ ```bash
6
+ listpick -i ./examples/input_files/polynomials.tsv
7
+ ```
8
+
9
+ Select two columns of cells that you want to plot and then hit |.
10
+
11
+ Type or paste the following into the pipe input field:
12
+
13
+ ```gnuplot -p -e 'plot "/dev/stdin" with lines'```
@@ -0,0 +1,30 @@
1
+ #!/bin/python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Create a Picker with a dynamic footer string that shows the current time, updating once per second.
5
+
6
+ Author: GrimAndGreedy
7
+ License: MIT
8
+ """
9
+
10
+ from listpick.listpick_app import Picker, close_curses, start_curses
11
+ from datetime import datetime
12
+
13
+
14
+ l = [["Time"], ["in"], ["footer"], ["string"]]
15
+
16
+ stdscr = start_curses()
17
+ x = Picker(
18
+ stdscr = stdscr,
19
+ items = l,
20
+ title="Footer string example",
21
+ footer_string_auto_refresh=True,
22
+ footer_timer=1.0,
23
+ footer_string_refresh_function=lambda:str(datetime.now()).split('.')[0],
24
+ )
25
+ selected_indices, opts, picker_data = x.run()
26
+
27
+ close_curses(stdscr)
28
+
29
+ print(f"Selected: {selected_indices}")
30
+ print(f"Opts: {opts}")
@@ -0,0 +1,54 @@
1
+ #!/bin/python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Create a basic picker with a title, header, items, and highlights.
5
+
6
+ Author: GrimAndGreedy
7
+ License: MIT
8
+ """
9
+
10
+ import sys, os
11
+ from listpick.listpick_app import Picker, close_curses, start_curses
12
+
13
+ l = [["The", "many"], ["words", "of"]]
14
+ l += [["the", "Athenians"], ["I", "do"]]
15
+ l += [["not", "understand."], ["They", "said"]]
16
+ l += [["a great", "deal"], ["in praise", "of themselves"]]
17
+ l += [["but", "nowhere"], ["denied", "that they"]]
18
+ l += [["are", "injuring"], ["our", "allies"]]
19
+
20
+ header=["Pericles", "Is Dead"]
21
+
22
+ highlights = [
23
+ {
24
+ "match": "praise",
25
+ "field": 0,
26
+ "color": 8,
27
+ },
28
+ {
29
+ "match": "theni..",
30
+ "field": 1,
31
+ "color": 9,
32
+ },
33
+ {
34
+ "match": ".*",
35
+ "row": 5,
36
+ "field": 1,
37
+ "color": 11,
38
+ },
39
+ ]
40
+
41
+ stdscr = start_curses()
42
+ x = Picker(
43
+ stdscr = stdscr,
44
+ items = l,
45
+ title="Picker Example",
46
+ header=header,
47
+ highlights=highlights,
48
+ )
49
+ selected_indices, opts, picker_data = x.run()
50
+
51
+ close_curses(stdscr)
52
+
53
+ print(f"Selected: {selected_indices}")
54
+ print(f"Opts: {opts}")
@@ -0,0 +1,28 @@
1
+ #!/bin/python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Create a basic picker with a title, header, and items.
5
+
6
+ Author: GrimAndGreedy
7
+ License: MIT
8
+ """
9
+
10
+ from listpick.listpick_app import Picker, close_curses, start_curses
11
+
12
+ l = [["1", "2"], ["3", "4"]]
13
+ header=["Pericles", "Is Dead"]
14
+
15
+ stdscr = start_curses()
16
+ x = Picker(
17
+ stdscr = stdscr,
18
+ items = l,
19
+ title="Test Picker",
20
+ header=header,
21
+ # highlights=highlights,
22
+ )
23
+ selected_indices, opts, picker_data = x.run()
24
+
25
+ close_curses(stdscr)
26
+
27
+ print(f"Selected: {selected_indices}")
28
+ print(f"Opts: {opts}")
@@ -0,0 +1,78 @@
1
+ #!/bin/python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Get a wikipedia table and display it in a Picker.
5
+
6
+ Author: GrimAndGreedy
7
+ License: MIT
8
+ """
9
+
10
+ import requests
11
+ from bs4 import BeautifulSoup
12
+ import pickle
13
+ from listpick.listpick_app import Picker, start_curses, close_curses
14
+
15
+
16
+ def fetch_and_parse_webpage(url: str) -> list:
17
+ """ Get list of tables from webpage at url. """
18
+ response = requests.get(url)
19
+ if response.status_code == 200:
20
+ soup = BeautifulSoup(response.content, 'html.parser')
21
+ tables = soup.find_all('table')
22
+ return [parse_table(table) for table in tables]
23
+ else:
24
+ raise Exception(f"Failed to fetch webpage: {response.status_code}")
25
+
26
+ def parse_table(table) -> list[list[str]]:
27
+ """ Convert a bs4 table to a list of lists. """
28
+ headers = [header.text.strip() for header in table.find('tr').find_all('th')]
29
+ rows = []
30
+ for row in table.find_all('tr')[1:]:
31
+ cells = [cell.text.strip() for cell in row.find_all(['td', 'th'])]
32
+ rows.append(cells)
33
+ return [headers] + rows
34
+
35
+ def save_data(data, filename: str) -> None:
36
+ """ Pickle data. """
37
+ with open(filename, 'wb') as file:
38
+ pickle.dump(data, file)
39
+
40
+ def load_data(filename: str, url: str) -> list:
41
+ """
42
+ Load tables from wikipedia page. Data is saved to `filename`.
43
+ If the tables have already been cached then we load the data and nothing is downloaded.
44
+ """
45
+ try:
46
+ with open(filename, 'rb') as file:
47
+ data = pickle.load(file)
48
+ return data
49
+ except FileNotFoundError:
50
+ print(f"File not found. Fetching data from the web.")
51
+ data = fetch_and_parse_webpage(url)
52
+ save_data(data, filename)
53
+ return data
54
+
55
+ if __name__ == "__main__":
56
+ url = 'https://en.wikipedia.org/wiki/2024-25_Premier_League'
57
+
58
+ # Filename for pickled data
59
+ # pickle_filename = './auxiallary_files/premier_league_tables_2024.pkl'
60
+ pickle_filename = f'./auxiallary_files/{url.split("/")[-1]}.pkl'
61
+ try:
62
+ tables = load_data(pickle_filename, url)
63
+ league_table_number = 4
64
+ items = tables[league_table_number][1:]
65
+ header = tables[league_table_number][0]
66
+ stdscr = start_curses()
67
+ app = Picker(
68
+ stdscr,
69
+ items=items,
70
+ header=header,
71
+ title="Premier League Table 2024-25",
72
+ colour_theme_number=3,
73
+ )
74
+ app.run()
75
+
76
+ close_curses(stdscr)
77
+ except:
78
+ pass
@@ -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.1",
19
+ version = "0.1.14.3",
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.",
@@ -716,6 +716,9 @@ class Picker:
716
716
  self.stdscr.erase()
717
717
 
718
718
  h, w = self.stdscr.getmaxyx()
719
+ # The height of the footer may need to be adjusted if the file changes.
720
+ self.footer.adjust_sizes(h,w)
721
+ self.calculate_section_sizes()
719
722
 
720
723
  # Test if the terminal is of a sufficient size to display the picker
721
724
  if not self.test_screen_size(): return None
@@ -742,7 +745,7 @@ class Picker:
742
745
  visible_columns_total_width = sum(visible_column_widths) + len(self.separator)*(len(visible_column_widths)-1)
743
746
 
744
747
  # Determine the number of items_per_page, top_size and bottom_size
745
- self.calculate_section_sizes()
748
+ # self.calculate_section_sizes()
746
749
 
747
750
  # top_space = self.top_gap
748
751
 
@@ -1225,6 +1228,9 @@ class Picker:
1225
1228
  "top_gap",
1226
1229
  "unicode_char_width",
1227
1230
  "show_row_header",
1231
+ "centre_in_terminal_vertical",
1232
+ "centre_in_cols",
1233
+ "centre_in_terminal",
1228
1234
  ]
1229
1235
 
1230
1236
  for var in variables:
@@ -1430,20 +1436,26 @@ class Picker:
1430
1436
  self.auto_refresh = not self.auto_refresh
1431
1437
  elif setting[1] == "h":
1432
1438
  self.highlights_hide = not self.highlights_hide
1439
+ elif setting.isnumeric():
1440
+ self.cursor_pos = max(0, min(int(setting), len(self.indexed_items)-1))
1441
+ elif setting.startswith("col") and setting[3:].isnumeric():
1442
+ col = int(setting[3:])
1443
+ if 0 <= col < len(self.column_widths):
1444
+ self.selected_column = col
1433
1445
 
1434
1446
  elif setting in ["nhl", "nohl", "nohighlights"]:
1435
1447
  # highlights = [highlight for highlight in highlights if "type" not in highlight or highlight["type"] != "search" ]
1436
1448
 
1437
1449
  self.highlights_hide = not self.highlights_hide
1438
- # elif setting[0] == "s":
1439
- # if 0 <= int(setting[1:]) < len(self.items[0]):
1440
- # self.sort_column = int(setting[1:])
1441
- # if len(self.indexed_items):
1442
- # current_pos = self.indexed_items[self.cursor_pos][0]
1443
- # 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 items based on new column
1444
- # if len(self.indexed_items):
1445
- # new_pos = [row[0] for row in self.indexed_items].index(current_pos)
1446
- # self.cursor_pos = new_pos
1450
+ elif setting.startswith("s") and setting[1:].isnumeric():
1451
+ if 0 <= int(setting[1:]) < len(self.items[0]):
1452
+ self.sort_column = int(setting[1:])
1453
+ if len(self.indexed_items):
1454
+ current_pos = self.indexed_items[self.cursor_pos][0]
1455
+ 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 items based on new column
1456
+ if len(self.indexed_items):
1457
+ new_pos = [row[0] for row in self.indexed_items].index(current_pos)
1458
+ self.cursor_pos = new_pos
1447
1459
  elif setting == "ct":
1448
1460
  self.centre_in_terminal = not self.centre_in_terminal
1449
1461
  elif setting == "cc":
@@ -1489,50 +1501,23 @@ class Picker:
1489
1501
  elif setting == "unicode":
1490
1502
  self.unicode_char_width = not self.unicode_char_width
1491
1503
  elif setting == "file_next":
1492
- if len(self.loaded_files) > 1:
1493
- self.command_stack.append(Command("setting", self.user_settings))
1494
- # Cache file state
1495
- self.loaded_file_states[self.loaded_file_index] = self.get_function_data()
1496
-
1497
- self.loaded_file_index = (self.loaded_file_index + 1) % len(self.loaded_files)
1498
- self.loaded_file = self.loaded_files[self.loaded_file_index]
1499
-
1500
- # If we already have a loaded state for this file
1501
- if self.loaded_file_states[self.loaded_file_index]:
1502
- self.set_function_data(self.loaded_file_states[self.loaded_file_index])
1503
- else:
1504
- self.set_function_data({}, reset_absent_variables=True)
1505
- self.load_file(self.loaded_file)
1504
+ self.command_stack.append(Command("setting", self.user_settings))
1505
+ self.switch_file(increment=1)
1506
+ elif setting == "file_prev":
1507
+ self.command_stack.append(Command("setting", self.user_settings))
1508
+ self.switch_file(increment=-1)
1509
+ # self.draw_screen(self.indexed_items, self.highlights)
1510
+ # self.stdscr.refresh()
1506
1511
 
1507
1512
  elif setting == "sheet_next":
1508
- if not os.path.exists(self.loaded_file):
1509
- self.notification(self.stdscr, message=f"File {repr(self.loaded_file)} not found.")
1510
- return None
1511
- if len(self.sheets) > 1:
1512
- self.command_stack.append(Command("setting", self.user_settings))
1513
-
1514
- # Cache sheet state
1515
- self.sheet_states[self.sheet_index] = self.get_function_data()
1516
- self.sheet_index = (self.sheet_index + 1) % len(self.sheets)
1517
- self.sheet_name = self.sheets[self.sheet_index]
1518
-
1519
- # If we already have a loaded state for this file
1520
- if self.sheet_states[self.sheet_index]:
1521
- self.set_function_data(self.sheet_states[self.sheet_index])
1522
- else:
1523
- function_data = {
1524
- "sheet_index": self.sheet_index,
1525
- "sheet_name": self.sheet_name,
1526
- "sheet_states":self.sheet_states,
1527
- "sheets": self.sheets,
1528
- }
1529
- self.set_function_data(function_data, reset_absent_variables=True)
1530
- self.load_sheet(self.loaded_file, sheet_number=self.sheet_index)
1531
-
1513
+ self.command_stack.append(Command("setting", self.user_settings))
1514
+ self.switch_sheet(increment=1)
1515
+ elif setting == "sheet_prev":
1516
+ self.command_stack.append(Command("setting", self.user_settings))
1517
+ self.switch_sheet(increment=-1)
1532
1518
 
1533
1519
  elif setting.startswith("ft"):
1534
1520
  if len(setting) > 2 and setting[2:].isnumeric():
1535
-
1536
1521
  num = int(setting[2:])
1537
1522
  self.footer_style = max(len(self.footer_options)-1, num)
1538
1523
  self.footer = self.footer_options[self.footer_style]
@@ -2099,7 +2084,50 @@ class Picker:
2099
2084
 
2100
2085
  self.initialise_variables()
2101
2086
 
2087
+ def switch_file(self, increment=1) -> None:
2088
+ """ Go to the next file. """
2089
+ if len(self.loaded_files) <= 1:
2090
+ return None
2091
+
2092
+ # Cache file state
2093
+ self.loaded_file_states[self.loaded_file_index] = self.get_function_data()
2102
2094
 
2095
+ self.loaded_file_index = (self.loaded_file_index + increment) % len(self.loaded_files)
2096
+ self.loaded_file = self.loaded_files[self.loaded_file_index]
2097
+
2098
+ # If we already have a loaded state for this file
2099
+ if self.loaded_file_states[self.loaded_file_index]:
2100
+ self.set_function_data(self.loaded_file_states[self.loaded_file_index])
2101
+ else:
2102
+ self.set_function_data({}, reset_absent_variables=True)
2103
+ self.load_file(self.loaded_file)
2104
+
2105
+
2106
+ def switch_sheet(self, increment=1) -> None:
2107
+ if not os.path.exists(self.loaded_file):
2108
+ self.notification(self.stdscr, message=f"File {repr(self.loaded_file)} not found.")
2109
+ return None
2110
+ if len(self.sheets) <= 1:
2111
+ return None
2112
+
2113
+ # Cache sheet state
2114
+ self.sheet_states[self.sheet_index] = self.get_function_data()
2115
+
2116
+ self.sheet_index = (self.sheet_index + increment) % len(self.sheets)
2117
+ self.sheet_name = self.sheets[self.sheet_index]
2118
+
2119
+ # If we already have a loaded state for this file
2120
+ if self.sheet_states[self.sheet_index]:
2121
+ self.set_function_data(self.sheet_states[self.sheet_index])
2122
+ else:
2123
+ function_data = {
2124
+ "sheet_index": self.sheet_index,
2125
+ "sheet_name": self.sheet_name,
2126
+ "sheet_states":self.sheet_states,
2127
+ "sheets": self.sheets,
2128
+ }
2129
+ self.set_function_data(function_data, reset_absent_variables=True)
2130
+ self.load_sheet(self.loaded_file, sheet_number=self.sheet_index)
2103
2131
 
2104
2132
 
2105
2133
 
@@ -2239,12 +2267,12 @@ class Picker:
2239
2267
  version = metadata.version('listpick')
2240
2268
 
2241
2269
  info_items = [
2242
- [" Listpick info:", "-*"*30],
2270
+ [" Listpick info", "-*"*30],
2243
2271
  ["",""],
2244
2272
  ["listpick version", f"{version}"],
2245
2273
 
2246
2274
  ["",""],
2247
- [" Global:", "-*"*30],
2275
+ [" Global", "-*"*30],
2248
2276
  ["",""],
2249
2277
  ["current_file", self.loaded_file],
2250
2278
  ["loaded_files", repr(self.loaded_files)],
@@ -2257,11 +2285,12 @@ class Picker:
2257
2285
  ["debug level", f"{repr(self.debug_level)}"],
2258
2286
 
2259
2287
  ["",""],
2260
- [" Current File:", "-*"*30],
2288
+ [" Current File", "-*"*30],
2261
2289
  ["",""],
2262
- ["row/row count", f"{self.cursor_pos}/{len(self.indexed_items)}"],
2263
- ["total rows", f"{len(self.items)}"],
2264
- ["selections", f"{self.selected_cells_by_row}"],
2290
+ # ["row/row count", f"{self.cursor_pos}/{len(self.indexed_items)}"],
2291
+ ["Current row", f"{self.cursor_pos}/{len(self.indexed_items)}"],
2292
+ ["Total rows", f"{len(self.items)}"],
2293
+ ["Selection count", f"{self.selected_cells_by_row}"],
2265
2294
  ["current_sheet", self.sheet_name],
2266
2295
  ["sheets", repr(self.sheets)],
2267
2296
  ["current column/column_count", f"{self.selected_column}/{len(self.column_widths)}"],
@@ -2272,7 +2301,7 @@ class Picker:
2272
2301
  ["id_column", f"{self.id_column}"],
2273
2302
 
2274
2303
  ["",""],
2275
- [" Display options:", "-*"*30],
2304
+ [" Display options", "-*"*30],
2276
2305
  ["",""],
2277
2306
  ["show_header", str(self.show_header)],
2278
2307
  ["show_footer", repr(self.show_footer)],
@@ -2293,20 +2322,29 @@ class Picker:
2293
2322
  ]
2294
2323
 
2295
2324
  data = self.get_function_data()
2296
- del data["indexed_items"]
2297
- del data["selections"]
2298
- del data["selected_cells_by_row"]
2299
- del data["cell_selections"]
2300
- del data["items"]
2301
- del data["require_option"]
2302
- del data["option_functions"]
2325
+ data["indexed_items"] = f"[...] length = {len(data['indexed_items'])}"
2326
+ data["selections"] = f"[...] length = {len(data['selections'])}"
2327
+ data["selected_cells_by_row"] = f"[...] length = {len(data['selected_cells_by_row'])}"
2328
+ data["cell_selections"] = f"[...] length = {len(data['cell_selections'])}"
2329
+ data["items"] = f"[...] length = {len(data['items'])}"
2330
+ data["require_option"] = f"[...] length = {len(data['require_option'])}"
2331
+ data["option_functions"] = f"[...] length = {len(data['option_functions'])}"
2332
+ data["loaded_file_states"] = f"[...] length = {len(data['loaded_file_states'])}"
2333
+ data["sheet_states"] = f"[...] length = {len(data['sheet_states'])}"
2303
2334
  info_items += [
2304
2335
  ["",""],
2305
- [" get_function_data():", "-*"*30],
2336
+ [" get_function_data()", "-*"*30],
2306
2337
  ["",""],
2307
2338
  ["show_header", str(self.show_header)],
2308
2339
  ]
2309
2340
  info_items += [[key, repr(value)] for key, value in data.items()]
2341
+
2342
+
2343
+ for row in info_items:
2344
+ if row[1] == "-*"*30:
2345
+ continue
2346
+ row[0] = " " + row[0]
2347
+
2310
2348
  info_header = ["Option", "Value"]
2311
2349
  info_data = {
2312
2350
  "items": info_items,
@@ -2405,13 +2443,18 @@ class Picker:
2405
2443
  options += [["rh", "Toggle row header"]]
2406
2444
  options += [["modes", "Toggle modes"]]
2407
2445
  options += [["ft", "Cycle through footer styles (accepts ft#)"]]
2446
+ options += [["file_next", "Go to the next open file."]]
2447
+ options += [["file_prev", "Go to the previous open file."]]
2448
+ options += [["sheet_next", "Go to the next sheet."]]
2449
+ options += [["sheet_prev", "Go to the previous sheet."]]
2408
2450
  options += [["unicode", "Toggle b/w using len and wcwidth to calculate char width."]]
2409
- options += [[f"s{i}", f"Select col. {i}"] for i in range(len(self.items[0]))]
2410
- options += [[f"!{i}", f"Toggle col. {i}"] for i in range(len(self.items[0]))]
2411
2451
  options += [["ara", "Add empty row after cursor."]]
2412
2452
  options += [["arb", "Add empty row before the cursor."]]
2413
2453
  options += [["aca", "Add empty column after the selected column."]]
2414
2454
  options += [["acb", "Add empty column before the selected column."]]
2455
+ options += [[f"col{i}", f"Select column {i}"] for i in range(len(self.items[0]))]
2456
+ options += [[f"s{i}", f"Sort by column {i}"] for i in range(len(self.items[0]))]
2457
+ options += [[f"!{i}", f"Toggle visibility of column {i}"] for i in range(len(self.items[0]))]
2415
2458
 
2416
2459
 
2417
2460
  settings_options_header = ["Key", "Setting"]
@@ -3031,14 +3074,10 @@ class Picker:
3031
3074
  # Re-sort self.items after applying filter
3032
3075
  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
3033
3076
  elif self.check_key("file_next", key, self.keys_dict):
3034
- if len(self.loaded_files):
3035
- self.loaded_file_index = (self.loaded_file_index + 1) % len(self.loaded_files)
3036
- self.loaded_file = self.loaded_files[self.loaded_file_index]
3077
+ self.switch_file(increment=1)
3037
3078
 
3038
3079
  elif self.check_key("file_prev", key, self.keys_dict):
3039
- if len(self.loaded_files):
3040
- self.loaded_file_index = (self.loaded_file_index - 1) % len(self.loaded_files)
3041
- self.loaded_file = self.loaded_files[self.loaded_file_index]
3080
+ self.switch_file(increment=-1)
3042
3081
 
3043
3082
  elif self.check_key("pipe_input", key, self.keys_dict):
3044
3083
  self.logger.info(f"key_function pipe_input")
@@ -116,6 +116,9 @@ def build_help_rows(keys_dict: dict) -> list[list[str]]:
116
116
  "add_row_before": "Insert row before cursor.",
117
117
  "add_column_after": "Insert column after cursor.",
118
118
  "add_row_after": "Insert row after cursor.",
119
+ "info": "Display info screen.",
120
+ "file_next": "Go to the next open file.",
121
+ "file_prev": "Go to the previous open file.",
119
122
  }
120
123
  sections = {
121
124
  "Navigation:": [ "cursor_down", "cursor_up", "half_page_up", "half_page_down", "page_up", "page_down", "cursor_bottom", "cursor_top", "five_up", "five_down", "scroll_right", "scroll_left", "scroll_far_right", "scroll_far_left" ],
@@ -47,42 +47,51 @@ class StandardFooter(Footer):
47
47
  else: self.height = 2
48
48
  except:
49
49
  logger.error("Error encountered when running StandardFooter.get_state")
50
- def draw(self, h, w):
51
- state = self.get_state()
52
- # Fill background
53
50
 
51
+ self.footer_string_y = 0
52
+ self.picker_info_y = 1
53
+ self.sort_info_y = 2
54
+ self.sheets_y = 3
55
+ self.files_y = 4
56
+ def adjust_sizes(self, h, w):
57
+ state = self.get_state()
54
58
 
55
- sheets_y=-1
59
+ self.sheets_y=-1
56
60
  if state["footer_string"]:
57
-
58
-
59
- footer_string_y = h-1
60
- picker_info_y = h-3
61
- sort_info_y = h-2
61
+ self.footer_string_y = h-1
62
+ self.picker_info_y = h-3
63
+ self.sort_info_y = h-2
62
64
 
63
65
  self.height = 3
64
66
 
65
67
  else:
66
- picker_info_y = h-2
67
- sort_info_y = h-1
68
- footer_string_y = -1
68
+ self.picker_info_y = h-2
69
+ self.sort_info_y = h-1
70
+ self.footer_string_y = -1
69
71
  self.height = 2
70
72
 
71
73
  if len(state["sheets"]) > 1:
72
74
  self.height += 1
73
- picker_info_y -= 1
74
- sort_info_y -= 1
75
- footer_string_y -= 1
76
- sheets_y = h-1
75
+ self.picker_info_y -= 1
76
+ self.sort_info_y -= 1
77
+ self.footer_string_y -= 1
78
+ self.sheets_y = h-1
77
79
 
78
80
  if len(state["loaded_files"]) > 1 and state["loaded_file"] in state["loaded_files"]:
79
81
  self.height += 1
80
- picker_info_y -= 1
81
- sort_info_y -= 1
82
- footer_string_y -= 1
83
- sheets_y -= 1
82
+ self.picker_info_y -= 1
83
+ self.sort_info_y -= 1
84
+ self.footer_string_y -= 1
85
+ self.sheets_y -= 1
86
+
87
+ self.files_y = h-1
88
+
89
+ def draw(self, h, w):
90
+ state = self.get_state()
91
+ # Fill background
92
+
93
+ self.adjust_sizes(h, w)
84
94
 
85
- files_y = h-1
86
95
 
87
96
 
88
97
  for i in range(self.height):
@@ -101,18 +110,18 @@ class StandardFooter(Footer):
101
110
  current_file_x = sum((len(x) for x in files[:idx])) + idx*len(sep)
102
111
  current_file_str = state["loaded_file"].split("/")[-1]
103
112
  current_file_x_end = current_file_x + len(current_file_str) + 2
104
- self.stdscr.addstr(files_y, 0, ' '*(w-1), curses.color_pair(self.colours_start+4))
113
+ self.stdscr.addstr(self.files_y, 0, ' '*(w-1), curses.color_pair(self.colours_start+4))
105
114
  if current_file_x_end < w:
106
115
 
107
- self.stdscr.addstr(files_y, 0, f" {files_str}", curses.color_pair(self.colours_start+4))
116
+ self.stdscr.addstr(self.files_y, 0, f" {files_str}", curses.color_pair(self.colours_start+4))
108
117
 
109
- self.stdscr.addstr(files_y, current_file_x, f" {current_file_str}{sep[0]}", curses.color_pair(self.colours_start+4) | curses.A_REVERSE)
118
+ self.stdscr.addstr(self.files_y, current_file_x, f" {current_file_str}{sep[0]}", curses.color_pair(self.colours_start+4) | curses.A_REVERSE)
110
119
  else:
111
120
  files_str = sep.join(files)
112
121
  files_str = files_str[current_file_x_end-w:current_file_x_end][:w-2]
113
- self.stdscr.addstr(files_y, 0, f" {files_str}", curses.color_pair(self.colours_start+4))
122
+ self.stdscr.addstr(self.files_y, 0, f" {files_str}", curses.color_pair(self.colours_start+4))
114
123
 
115
- self.stdscr.addstr(files_y, w - (len(current_file_str)+3), f" {current_file_str}{sep[0]}", curses.color_pair(self.colours_start+4) | curses.A_REVERSE)
124
+ self.stdscr.addstr(self.files_y, w - (len(current_file_str)+3), f" {current_file_str}{sep[0]}", curses.color_pair(self.colours_start+4) | curses.A_REVERSE)
116
125
 
117
126
  if len(state["sheets"]) > 1:
118
127
 
@@ -127,18 +136,18 @@ class StandardFooter(Footer):
127
136
  current_sheet_x = sum((len(x) for x in sheets[:idx])) + idx*len(sep)
128
137
  current_sheet_str = state["sheet_name"].split("/")[-1]
129
138
  current_sheet_x_end = current_sheet_x + len(current_sheet_str) + 2
130
- self.stdscr.addstr(sheets_y, 0, ' '*(w-1), curses.color_pair(self.colours_start+4))
139
+ self.stdscr.addstr(self.sheets_y, 0, ' '*(w-1), curses.color_pair(self.colours_start+4))
131
140
  if current_sheet_x_end < w:
132
141
 
133
- self.stdscr.addstr(sheets_y, 0, f" {sheets_str}", curses.color_pair(self.colours_start+4))
142
+ self.stdscr.addstr(self.sheets_y, 0, f" {sheets_str}", curses.color_pair(self.colours_start+4))
134
143
 
135
- self.stdscr.addstr(sheets_y, current_sheet_x, f" {current_sheet_str}{sep[0]}", curses.color_pair(self.colours_start+4) | curses.A_REVERSE)
144
+ self.stdscr.addstr(self.sheets_y, current_sheet_x, f" {current_sheet_str}{sep[0]}", curses.color_pair(self.colours_start+4) | curses.A_REVERSE)
136
145
  else:
137
146
  sheets_str = sep.join(sheets)
138
147
  sheets_str = sheets_str[current_sheet_x_end-w:current_sheet_x_end][:w-2]
139
- self.stdscr.addstr(sheets_y, 0, f" {sheets_str}", curses.color_pair(self.colours_start+4))
148
+ self.stdscr.addstr(self.sheets_y, 0, f" {sheets_str}", curses.color_pair(self.colours_start+4))
140
149
 
141
- self.stdscr.addstr(sheets_y, w - (len(current_sheet_str)+3), f" {current_sheet_str}{sep[0]}", curses.color_pair(self.colours_start+4) | curses.A_REVERSE)
150
+ self.stdscr.addstr(self.sheets_y, w - (len(current_sheet_str)+3), f" {current_sheet_str}{sep[0]}", curses.color_pair(self.colours_start+4) | curses.A_REVERSE)
142
151
 
143
152
 
144
153
 
@@ -148,8 +157,8 @@ class StandardFooter(Footer):
148
157
 
149
158
  disp_string = f"{state["footer_string"][:footer_string_width]}"
150
159
  disp_string = f" {disp_string:>{footer_string_width-2}} "
151
- self.stdscr.addstr(footer_string_y, w-footer_string_width-1, " "*footer_string_width, curses.color_pair(self.colours_start+24))
152
- self.stdscr.addstr(footer_string_y, w-footer_string_width-1, f"{disp_string}", curses.color_pair(self.colours_start+24))
160
+ self.stdscr.addstr(self.footer_string_y, w-footer_string_width-1, " "*footer_string_width, curses.color_pair(self.colours_start+24))
161
+ self.stdscr.addstr(self.footer_string_y, w-footer_string_width-1, f"{disp_string}", curses.color_pair(self.colours_start+24))
153
162
 
154
163
 
155
164
 
@@ -177,7 +186,7 @@ class StandardFooter(Footer):
177
186
 
178
187
  # Maximum chars that should be displayed
179
188
  max_chars = min(len(cursor_disp_str)+2, w)
180
- self.stdscr.addstr(picker_info_y, w-max_chars, f"{cursor_disp_str:>{max_chars-2}} ", curses.color_pair(self.colours_start+20))
189
+ self.stdscr.addstr(self.picker_info_y, w-max_chars, f"{cursor_disp_str:>{max_chars-2}} ", curses.color_pair(self.colours_start+20))
181
190
 
182
191
 
183
192
  # Sort info
@@ -187,7 +196,7 @@ class StandardFooter(Footer):
187
196
  sort_order_info = "▼" if state["sort_reverse"][state['sort_column']] else "▲"
188
197
  sort_disp_str = f" Sort: ({sort_column_info}, {sort_method_info}, {sort_order_info}) "
189
198
  max_chars = min(len(sort_disp_str)+2, w)
190
- self.stdscr.addstr(sort_info_y, w-max_chars, f"{sort_disp_str:>{max_chars-1}}", curses.color_pair(self.colours_start+20))
199
+ self.stdscr.addstr(self.sort_info_y, w-max_chars, f"{sort_disp_str:>{max_chars-1}}", curses.color_pair(self.colours_start+20))
191
200
 
192
201
  self.stdscr.refresh()
193
202
 
@@ -205,6 +214,9 @@ class CompactFooter(Footer):
205
214
  self.get_state = get_state_function
206
215
  self.height = 1
207
216
 
217
+ def adjust_sizes(self, h, w):
218
+ pass
219
+
208
220
  def draw(self, h, w):
209
221
  state = self.get_state()
210
222
 
@@ -268,6 +280,10 @@ class NoFooter(Footer):
268
280
  self.colours_start = colours_start
269
281
  self.get_state = get_state_function
270
282
  self.height = 0
283
+
284
+ def adjust_sizes(self, h, w):
285
+ pass
286
+
271
287
  def draw(self, h, w):
272
288
  state = self.get_state()
273
289
 
@@ -0,0 +1,37 @@
1
+ Thank you for filling out a Git bug report!
2
+ Please answer the following questions to help us understand your issue.
3
+
4
+ What did you do before the bug happened? (Steps to reproduce your issue)
5
+
6
+ What did you expect to happen? (Expected behavior)
7
+
8
+ What happened instead? (Actual behavior)
9
+
10
+ What's different between what you expected and what actually happened?
11
+
12
+ Anything else you want to add:
13
+
14
+ Please review the rest of the bug report below.
15
+ You can delete any lines you don't wish to share.
16
+
17
+
18
+ [System Info]
19
+ git version:
20
+ git version 2.50.1
21
+ cpu: x86_64
22
+ built from commit: d82adb61ba2fd11d8f2587fca1b6bd7925ce4044
23
+ sizeof-long: 8
24
+ sizeof-size_t: 8
25
+ shell-path: /bin/sh
26
+ libcurl: 8.14.1
27
+ OpenSSL: OpenSSL 3.5.1 1 Jul 2025
28
+ zlib-ng: 2.2.4
29
+ SHA-1: SHA1_DC
30
+ SHA-256: SHA256_BLK
31
+ uname: Linux 6.15.9-arch1-1 #1 SMP PREEMPT_DYNAMIC Sat, 02 Aug 2025 01:20:06 +0000 x86_64
32
+ compiler info: gnuc: 15.1
33
+ libc info: glibc: 2.42
34
+ $SHELL (typically, interactive shell): /usr/bin/zsh
35
+
36
+
37
+ [Enabled Hooks]
@@ -15,8 +15,8 @@ picker_keys = {
15
15
  "help": [ord('?')],
16
16
  "exit": [ord('q')],
17
17
  "full_exit": [3], # Ctrl+c
18
- "move_column_left": [ord('{')],
19
- "move_column_right": [ord('}')],
18
+ # "move_column_left": [ord('{')],
19
+ # "move_column_right": [ord('}')],
20
20
  "cursor_down": [ord('j'), curses.KEY_DOWN],
21
21
  "cursor_up": [ord('k'), curses.KEY_UP],
22
22
  "half_page_up": [ord('u')],
@@ -81,6 +81,8 @@ picker_keys = {
81
81
  # "add_row_before": [ord('=')],
82
82
  "add_row_after": [ord('=')],
83
83
  "info": [ord('i')],
84
+ "file_next": [ord('}')],
85
+ "file_prev": [ord('{')],
84
86
  }
85
87
 
86
88
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: listpick
3
- Version: 0.1.14.1
3
+ Version: 0.1.14.3
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
@@ -9,6 +9,17 @@ setup.py
9
9
  assets/aria2tui_screenshot.png
10
10
  assets/file_compare.png
11
11
  assets/lpfman.png
12
+ examples/data_generation/list_files.toml
13
+ examples/data_generation/list_files_empty.toml
14
+ examples/data_generation/video_duplicates.toml
15
+ examples/data_generation/video_mediainfo.toml
16
+ examples/input_files/polynomials.tsv
17
+ examples/input_guides/gnuplot_graph.md
18
+ examples/picker/footer_string_example.py
19
+ examples/picker/picker_example.py
20
+ examples/picker/template.py
21
+ examples/picker/wikipedia_table.py
22
+ examples/picker/auxiallary_files/2024-25_Premier_League.pkl
12
23
  src/listpick/__init__.py
13
24
  src/listpick/__main__.py
14
25
  src/listpick/listpick_app.py
@@ -21,6 +32,7 @@ src/listpick.egg-info/top_level.txt
21
32
  src/listpick/ui/__init__.py
22
33
  src/listpick/ui/build_help.py
23
34
  src/listpick/ui/footer.py
35
+ src/listpick/ui/git-bugreport-2025-08-16-1438.txt
24
36
  src/listpick/ui/help_screen.py
25
37
  src/listpick/ui/input_field.py
26
38
  src/listpick/ui/keys.py
File without changes
File without changes
File without changes
File without changes
File without changes