listpick 0.1.14.2__tar.gz → 0.1.14.4__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.
Potentially problematic release.
This version of listpick might be problematic. Click here for more details.
- {listpick-0.1.14.2 → listpick-0.1.14.4}/CHANGELOG.md +2 -0
- {listpick-0.1.14.2/src/listpick.egg-info → listpick-0.1.14.4}/PKG-INFO +1 -1
- {listpick-0.1.14.2 → listpick-0.1.14.4}/TODO.md +4 -0
- listpick-0.1.14.4/examples/data_generation/list_files.toml +23 -0
- listpick-0.1.14.4/examples/data_generation/list_files_empty.toml +22 -0
- listpick-0.1.14.4/examples/data_generation/video_duplicates.toml +36 -0
- listpick-0.1.14.4/examples/data_generation/video_mediainfo.toml +32 -0
- listpick-0.1.14.4/examples/input_files/polynomials.tsv +31 -0
- listpick-0.1.14.4/examples/input_guides/gnuplot_graph.md +13 -0
- listpick-0.1.14.4/examples/picker/auxiallary_files/2024-25_Premier_League.pkl +0 -0
- listpick-0.1.14.4/examples/picker/footer_string_example.py +30 -0
- listpick-0.1.14.4/examples/picker/picker_example.py +54 -0
- listpick-0.1.14.4/examples/picker/template.py +28 -0
- listpick-0.1.14.4/examples/picker/wikipedia_table.py +78 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/setup.py +1 -1
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/listpick_app.py +63 -36
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/ui/footer.py +51 -35
- listpick-0.1.14.4/src/listpick/ui/git-bugreport-2025-08-16-1438.txt +37 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/utils/table_to_list_of_lists.py +15 -8
- {listpick-0.1.14.2 → listpick-0.1.14.4/src/listpick.egg-info}/PKG-INFO +1 -1
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick.egg-info/SOURCES.txt +12 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/.gitignore +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/LICENSE.txt +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/README.md +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/assets/aria2tui_screenshot.png +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/assets/file_compare.png +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/assets/lpfman.png +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/listpick.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/requirements.txt +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/setup.cfg +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/__init__.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/__main__.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/ui/__init__.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/ui/build_help.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/ui/help_screen.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/ui/input_field.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/ui/keys.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/ui/pane_stuff.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/ui/picker_colours.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/utils/__init__.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/utils/clipboard_operations.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/utils/config.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/utils/dump.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/utils/filtering.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/utils/generate_data.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/utils/options_selectors.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/utils/paste_operations.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/utils/picker_log.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/utils/search_and_filter_utils.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/utils/searching.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/utils/sorting.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick/utils/utils.py +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick.egg-info/dependency_links.txt +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick.egg-info/entry_points.txt +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick.egg-info/requires.txt +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/src/listpick.egg-info/top_level.txt +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/tests/kitty_control.sh +0 -0
- {listpick-0.1.14.2 → listpick-0.1.14.4}/tests/sorting_dates.csv +0 -0
|
@@ -5,6 +5,8 @@ Note that the changes between 0.1.11.0 and 1.1.12.0 are listed under 0.1.11
|
|
|
5
5
|
- Added info screen to display all information on the running Picker.
|
|
6
6
|
- Added keys for file_next and file_prev
|
|
7
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
|
|
8
10
|
|
|
9
11
|
## [0.1.14] 2025-08-20
|
|
10
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.4",
|
|
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.",
|
|
@@ -573,10 +573,6 @@ class Picker:
|
|
|
573
573
|
# If a sort is passed
|
|
574
574
|
if len(self.indexed_items) > 0:
|
|
575
575
|
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
|
|
576
|
-
# if len(self.items[0]) == 1:
|
|
577
|
-
# self.number_columns = False
|
|
578
|
-
|
|
579
|
-
|
|
580
576
|
|
|
581
577
|
h, w = self.stdscr.getmaxyx()
|
|
582
578
|
|
|
@@ -677,7 +673,14 @@ class Picker:
|
|
|
677
673
|
# Update current column index
|
|
678
674
|
self.selected_column = new_index
|
|
679
675
|
|
|
680
|
-
def test_screen_size(self):
|
|
676
|
+
def test_screen_size(self) -> bool:
|
|
677
|
+
"""
|
|
678
|
+
Determine if the terminal is large enough to display the picker.
|
|
679
|
+
If the terminal is too small then display a message saying so.
|
|
680
|
+
|
|
681
|
+
Returns: True if terminal is large enough to display the Picker.
|
|
682
|
+
|
|
683
|
+
"""
|
|
681
684
|
self.logger.debug("function: test_screen_size()")
|
|
682
685
|
h, w = self.stdscr.getmaxyx()
|
|
683
686
|
## Terminal too small to display Picker
|
|
@@ -689,9 +692,10 @@ class Picker:
|
|
|
689
692
|
return False
|
|
690
693
|
return True
|
|
691
694
|
|
|
692
|
-
def splash_screen(self, message=""):
|
|
693
|
-
self.logger.info(f"function: splash_screen({message})")
|
|
695
|
+
def splash_screen(self, message="") -> None:
|
|
694
696
|
""" Display a splash screen with a message. Useful when loading a large data set. """
|
|
697
|
+
|
|
698
|
+
self.logger.info(f"function: splash_screen({message})")
|
|
695
699
|
h, w =self.stdscr.getmaxyx()
|
|
696
700
|
self.stdscr.bkgd(' ', curses.color_pair(2))
|
|
697
701
|
try:
|
|
@@ -716,6 +720,9 @@ class Picker:
|
|
|
716
720
|
self.stdscr.erase()
|
|
717
721
|
|
|
718
722
|
h, w = self.stdscr.getmaxyx()
|
|
723
|
+
# The height of the footer may need to be adjusted if the file changes.
|
|
724
|
+
self.footer.adjust_sizes(h,w)
|
|
725
|
+
self.calculate_section_sizes()
|
|
719
726
|
|
|
720
727
|
# Test if the terminal is of a sufficient size to display the picker
|
|
721
728
|
if not self.test_screen_size(): return None
|
|
@@ -742,7 +749,7 @@ class Picker:
|
|
|
742
749
|
visible_columns_total_width = sum(visible_column_widths) + len(self.separator)*(len(visible_column_widths)-1)
|
|
743
750
|
|
|
744
751
|
# Determine the number of items_per_page, top_size and bottom_size
|
|
745
|
-
self.calculate_section_sizes()
|
|
752
|
+
# self.calculate_section_sizes()
|
|
746
753
|
|
|
747
754
|
# top_space = self.top_gap
|
|
748
755
|
|
|
@@ -851,14 +858,6 @@ class Picker:
|
|
|
851
858
|
except:
|
|
852
859
|
pass
|
|
853
860
|
|
|
854
|
-
# Draw:
|
|
855
|
-
# 1. standard row
|
|
856
|
-
# 2. highlights l0
|
|
857
|
-
# 3. selected
|
|
858
|
-
# 4. above-selected highlights l1
|
|
859
|
-
# 5. cursor
|
|
860
|
-
# 6. top-level highlights l2
|
|
861
|
-
## Display rows and highlights
|
|
862
861
|
|
|
863
862
|
def sort_highlights(highlights):
|
|
864
863
|
"""
|
|
@@ -918,6 +917,15 @@ class Picker:
|
|
|
918
917
|
except:
|
|
919
918
|
pass
|
|
920
919
|
|
|
920
|
+
# Draw:
|
|
921
|
+
# 1. standard row
|
|
922
|
+
# 2. highlights l0
|
|
923
|
+
# 3. selected
|
|
924
|
+
# 4. above-selected highlights l1
|
|
925
|
+
# 5. cursor
|
|
926
|
+
# 6. top-level highlights l2
|
|
927
|
+
## Display rows and highlights
|
|
928
|
+
|
|
921
929
|
l0_highlights, l1_highlights, l2_highlights = sort_highlights(self.highlights)
|
|
922
930
|
|
|
923
931
|
|
|
@@ -1225,6 +1233,9 @@ class Picker:
|
|
|
1225
1233
|
"top_gap",
|
|
1226
1234
|
"unicode_char_width",
|
|
1227
1235
|
"show_row_header",
|
|
1236
|
+
"centre_in_terminal_vertical",
|
|
1237
|
+
"centre_in_cols",
|
|
1238
|
+
"centre_in_terminal",
|
|
1228
1239
|
]
|
|
1229
1240
|
|
|
1230
1241
|
for var in variables:
|
|
@@ -1430,20 +1441,26 @@ class Picker:
|
|
|
1430
1441
|
self.auto_refresh = not self.auto_refresh
|
|
1431
1442
|
elif setting[1] == "h":
|
|
1432
1443
|
self.highlights_hide = not self.highlights_hide
|
|
1444
|
+
elif setting.isnumeric():
|
|
1445
|
+
self.cursor_pos = max(0, min(int(setting), len(self.indexed_items)-1))
|
|
1446
|
+
elif setting.startswith("col") and setting[3:].isnumeric():
|
|
1447
|
+
col = int(setting[3:])
|
|
1448
|
+
if 0 <= col < len(self.column_widths):
|
|
1449
|
+
self.selected_column = col
|
|
1433
1450
|
|
|
1434
1451
|
elif setting in ["nhl", "nohl", "nohighlights"]:
|
|
1435
1452
|
# highlights = [highlight for highlight in highlights if "type" not in highlight or highlight["type"] != "search" ]
|
|
1436
1453
|
|
|
1437
1454
|
self.highlights_hide = not self.highlights_hide
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1455
|
+
elif setting.startswith("s") and setting[1:].isnumeric():
|
|
1456
|
+
if 0 <= int(setting[1:]) < len(self.items[0]):
|
|
1457
|
+
self.sort_column = int(setting[1:])
|
|
1458
|
+
if len(self.indexed_items):
|
|
1459
|
+
current_pos = self.indexed_items[self.cursor_pos][0]
|
|
1460
|
+
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
|
|
1461
|
+
if len(self.indexed_items):
|
|
1462
|
+
new_pos = [row[0] for row in self.indexed_items].index(current_pos)
|
|
1463
|
+
self.cursor_pos = new_pos
|
|
1447
1464
|
elif setting == "ct":
|
|
1448
1465
|
self.centre_in_terminal = not self.centre_in_terminal
|
|
1449
1466
|
elif setting == "cc":
|
|
@@ -1494,6 +1511,8 @@ class Picker:
|
|
|
1494
1511
|
elif setting == "file_prev":
|
|
1495
1512
|
self.command_stack.append(Command("setting", self.user_settings))
|
|
1496
1513
|
self.switch_file(increment=-1)
|
|
1514
|
+
# self.draw_screen(self.indexed_items, self.highlights)
|
|
1515
|
+
# self.stdscr.refresh()
|
|
1497
1516
|
|
|
1498
1517
|
elif setting == "sheet_next":
|
|
1499
1518
|
self.command_stack.append(Command("setting", self.user_settings))
|
|
@@ -1504,7 +1523,6 @@ class Picker:
|
|
|
1504
1523
|
|
|
1505
1524
|
elif setting.startswith("ft"):
|
|
1506
1525
|
if len(setting) > 2 and setting[2:].isnumeric():
|
|
1507
|
-
|
|
1508
1526
|
num = int(setting[2:])
|
|
1509
1527
|
self.footer_style = max(len(self.footer_options)-1, num)
|
|
1510
1528
|
self.footer = self.footer_options[self.footer_style]
|
|
@@ -2254,12 +2272,12 @@ class Picker:
|
|
|
2254
2272
|
version = metadata.version('listpick')
|
|
2255
2273
|
|
|
2256
2274
|
info_items = [
|
|
2257
|
-
["
|
|
2275
|
+
[" Listpick info", "-*"*30],
|
|
2258
2276
|
["",""],
|
|
2259
2277
|
["listpick version", f"{version}"],
|
|
2260
2278
|
|
|
2261
2279
|
["",""],
|
|
2262
|
-
["
|
|
2280
|
+
[" Global", "-*"*30],
|
|
2263
2281
|
["",""],
|
|
2264
2282
|
["current_file", self.loaded_file],
|
|
2265
2283
|
["loaded_files", repr(self.loaded_files)],
|
|
@@ -2272,11 +2290,12 @@ class Picker:
|
|
|
2272
2290
|
["debug level", f"{repr(self.debug_level)}"],
|
|
2273
2291
|
|
|
2274
2292
|
["",""],
|
|
2275
|
-
["
|
|
2293
|
+
[" Current File", "-*"*30],
|
|
2276
2294
|
["",""],
|
|
2277
|
-
["row/row count", f"{self.cursor_pos}/{len(self.indexed_items)}"],
|
|
2278
|
-
["
|
|
2279
|
-
["
|
|
2295
|
+
# ["row/row count", f"{self.cursor_pos}/{len(self.indexed_items)}"],
|
|
2296
|
+
["Current row", f"{self.cursor_pos}/{len(self.indexed_items)}"],
|
|
2297
|
+
["Total rows", f"{len(self.items)}"],
|
|
2298
|
+
["Selection count", f"{self.selected_cells_by_row}"],
|
|
2280
2299
|
["current_sheet", self.sheet_name],
|
|
2281
2300
|
["sheets", repr(self.sheets)],
|
|
2282
2301
|
["current column/column_count", f"{self.selected_column}/{len(self.column_widths)}"],
|
|
@@ -2287,7 +2306,7 @@ class Picker:
|
|
|
2287
2306
|
["id_column", f"{self.id_column}"],
|
|
2288
2307
|
|
|
2289
2308
|
["",""],
|
|
2290
|
-
["
|
|
2309
|
+
[" Display options", "-*"*30],
|
|
2291
2310
|
["",""],
|
|
2292
2311
|
["show_header", str(self.show_header)],
|
|
2293
2312
|
["show_footer", repr(self.show_footer)],
|
|
@@ -2319,11 +2338,18 @@ class Picker:
|
|
|
2319
2338
|
data["sheet_states"] = f"[...] length = {len(data['sheet_states'])}"
|
|
2320
2339
|
info_items += [
|
|
2321
2340
|
["",""],
|
|
2322
|
-
["
|
|
2341
|
+
[" get_function_data()", "-*"*30],
|
|
2323
2342
|
["",""],
|
|
2324
2343
|
["show_header", str(self.show_header)],
|
|
2325
2344
|
]
|
|
2326
2345
|
info_items += [[key, repr(value)] for key, value in data.items()]
|
|
2346
|
+
|
|
2347
|
+
|
|
2348
|
+
for row in info_items:
|
|
2349
|
+
if row[1] == "-*"*30:
|
|
2350
|
+
continue
|
|
2351
|
+
row[0] = " " + row[0]
|
|
2352
|
+
|
|
2327
2353
|
info_header = ["Option", "Value"]
|
|
2328
2354
|
info_data = {
|
|
2329
2355
|
"items": info_items,
|
|
@@ -2427,12 +2453,13 @@ class Picker:
|
|
|
2427
2453
|
options += [["sheet_next", "Go to the next sheet."]]
|
|
2428
2454
|
options += [["sheet_prev", "Go to the previous sheet."]]
|
|
2429
2455
|
options += [["unicode", "Toggle b/w using len and wcwidth to calculate char width."]]
|
|
2430
|
-
options += [[f"s{i}", f"Select col. {i}"] for i in range(len(self.items[0]))]
|
|
2431
|
-
options += [[f"!{i}", f"Toggle col. {i}"] for i in range(len(self.items[0]))]
|
|
2432
2456
|
options += [["ara", "Add empty row after cursor."]]
|
|
2433
2457
|
options += [["arb", "Add empty row before the cursor."]]
|
|
2434
2458
|
options += [["aca", "Add empty column after the selected column."]]
|
|
2435
2459
|
options += [["acb", "Add empty column before the selected column."]]
|
|
2460
|
+
options += [[f"col{i}", f"Select column {i}"] for i in range(len(self.items[0]))]
|
|
2461
|
+
options += [[f"s{i}", f"Sort by column {i}"] for i in range(len(self.items[0]))]
|
|
2462
|
+
options += [[f"!{i}", f"Toggle visibility of column {i}"] for i in range(len(self.items[0]))]
|
|
2436
2463
|
|
|
2437
2464
|
|
|
2438
2465
|
settings_options_header = ["Key", "Setting"]
|
|
@@ -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]
|
|
@@ -144,11 +144,14 @@ def table_to_list(
|
|
|
144
144
|
import pandas as pd
|
|
145
145
|
ef = pd.ExcelFile(input_arg)
|
|
146
146
|
sheets = ef.sheet_names
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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)
|
|
151
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]
|
|
152
155
|
try:
|
|
153
156
|
header = list(df.columns)
|
|
154
157
|
except:
|
|
@@ -160,11 +163,15 @@ def table_to_list(
|
|
|
160
163
|
import pandas as pd
|
|
161
164
|
ef = pd.ExcelFile(input_arg)
|
|
162
165
|
sheets = ef.sheet_names
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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')
|
|
167
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
|
+
|
|
168
175
|
try:
|
|
169
176
|
header = list(df.columns)
|
|
170
177
|
except:
|
|
@@ -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
|
|
File without changes
|