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.
- {listpick-0.1.14.1 → listpick-0.1.14.3}/CHANGELOG.md +4 -0
- {listpick-0.1.14.1/src/listpick.egg-info → listpick-0.1.14.3}/PKG-INFO +1 -1
- {listpick-0.1.14.1 → listpick-0.1.14.3}/TODO.md +4 -0
- listpick-0.1.14.3/examples/data_generation/list_files.toml +23 -0
- listpick-0.1.14.3/examples/data_generation/list_files_empty.toml +22 -0
- listpick-0.1.14.3/examples/data_generation/video_duplicates.toml +36 -0
- listpick-0.1.14.3/examples/data_generation/video_mediainfo.toml +32 -0
- listpick-0.1.14.3/examples/input_files/polynomials.tsv +31 -0
- listpick-0.1.14.3/examples/input_guides/gnuplot_graph.md +13 -0
- listpick-0.1.14.3/examples/picker/auxiallary_files/2024-25_Premier_League.pkl +0 -0
- listpick-0.1.14.3/examples/picker/footer_string_example.py +30 -0
- listpick-0.1.14.3/examples/picker/picker_example.py +54 -0
- listpick-0.1.14.3/examples/picker/template.py +28 -0
- listpick-0.1.14.3/examples/picker/wikipedia_table.py +78 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/setup.py +1 -1
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/listpick_app.py +111 -72
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/build_help.py +3 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/footer.py +51 -35
- listpick-0.1.14.3/src/listpick/ui/git-bugreport-2025-08-16-1438.txt +37 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/keys.py +4 -2
- {listpick-0.1.14.1 → listpick-0.1.14.3/src/listpick.egg-info}/PKG-INFO +1 -1
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick.egg-info/SOURCES.txt +12 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/.gitignore +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/LICENSE.txt +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/README.md +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/assets/aria2tui_screenshot.png +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/assets/file_compare.png +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/assets/lpfman.png +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/listpick.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/requirements.txt +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/setup.cfg +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/__init__.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/__main__.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/__init__.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/help_screen.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/input_field.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/pane_stuff.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/ui/picker_colours.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/__init__.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/clipboard_operations.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/config.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/dump.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/filtering.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/generate_data.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/options_selectors.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/paste_operations.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/picker_log.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/search_and_filter_utils.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/searching.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/sorting.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/table_to_list_of_lists.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick/utils/utils.py +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick.egg-info/dependency_links.txt +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick.egg-info/entry_points.txt +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick.egg-info/requires.txt +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/src/listpick.egg-info/top_level.txt +0 -0
- {listpick-0.1.14.1 → listpick-0.1.14.3}/tests/kitty_control.sh +0 -0
- {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.
|
|
@@ -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.
|
|
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
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
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
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
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
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
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
|
-
["
|
|
2270
|
+
[" Listpick info", "-*"*30],
|
|
2243
2271
|
["",""],
|
|
2244
2272
|
["listpick version", f"{version}"],
|
|
2245
2273
|
|
|
2246
2274
|
["",""],
|
|
2247
|
-
["
|
|
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
|
-
["
|
|
2288
|
+
[" Current File", "-*"*30],
|
|
2261
2289
|
["",""],
|
|
2262
|
-
["row/row count", f"{self.cursor_pos}/{len(self.indexed_items)}"],
|
|
2263
|
-
["
|
|
2264
|
-
["
|
|
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
|
-
["
|
|
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
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
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
|
-
["
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|