listpick 0.1.15.19__py3-none-any.whl → 0.1.16.17__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- listpick/listpick_app.py +1235 -660
- listpick/pane/get_data.py +20 -0
- listpick/pane/left_pane_functions.py +198 -0
- listpick/pane/pane_functions.py +45 -5
- listpick/pane/pane_functions_1.py +175 -0
- listpick/pane/pane_utils.py +3 -3
- listpick/ui/build_help.py +37 -12
- listpick/ui/draw_screen.py +0 -0
- listpick/ui/footer.py +3 -3
- listpick/ui/input_field.py +1 -20
- listpick/ui/keys.py +16 -10
- listpick/ui/picker_colours.py +55 -0
- listpick/utils/generate_data.py +45 -2
- listpick/utils/generate_data_multiprocessing.py +10 -0
- listpick/utils/generate_data_multithreaded.py +234 -0
- listpick/utils/generate_data_utils.py +43 -0
- listpick/utils/user_input.py +7 -1
- listpick/utils/utils.py +17 -15
- {listpick-0.1.15.19.dist-info → listpick-0.1.16.17.dist-info}/METADATA +31 -42
- listpick-0.1.16.17.dist-info/RECORD +43 -0
- listpick-0.1.15.19.dist-info/RECORD +0 -37
- {listpick-0.1.15.19.dist-info → listpick-0.1.16.17.dist-info}/WHEEL +0 -0
- {listpick-0.1.15.19.dist-info → listpick-0.1.16.17.dist-info}/entry_points.txt +0 -0
- {listpick-0.1.15.19.dist-info → listpick-0.1.16.17.dist-info}/licenses/LICENSE.txt +0 -0
- {listpick-0.1.15.19.dist-info → listpick-0.1.16.17.dist-info}/top_level.txt +0 -0
listpick/pane/get_data.py
CHANGED
|
@@ -8,6 +8,8 @@ Author: GrimAndGreedy
|
|
|
8
8
|
License: MIT
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
+
from listpick.pane.pane_utils import get_file_attributes
|
|
12
|
+
|
|
11
13
|
def data_refresh_randint_by_row(data, state):
|
|
12
14
|
"""
|
|
13
15
|
Add a random number to the data if row id is the same.
|
|
@@ -93,3 +95,21 @@ def get_dl(data, state):
|
|
|
93
95
|
data[0].append(data[0][-1]+1)
|
|
94
96
|
data[1].append(dl)
|
|
95
97
|
return data
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def update_file_attributes(data, state):
|
|
101
|
+
"""
|
|
102
|
+
Get file attributes
|
|
103
|
+
|
|
104
|
+
data[0]: ["size: {}", filetype: {}, last modified: {}]
|
|
105
|
+
]
|
|
106
|
+
data[1]: id
|
|
107
|
+
"""
|
|
108
|
+
if state["indexed_items"]:
|
|
109
|
+
# id = state["indexed_items"][state["cursor_pos"]][1][state["id_column"]]
|
|
110
|
+
id = state["indexed_items"][state["cursor_pos"]][1][0]
|
|
111
|
+
else:
|
|
112
|
+
return [[], -1]
|
|
113
|
+
return [get_file_attributes(id), id]
|
|
114
|
+
|
|
115
|
+
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
#!/bin/python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
pane_functions.py
|
|
5
|
+
Functions which are run by a listpick Picker to display data in a pane.
|
|
6
|
+
|
|
7
|
+
Author: GrimAndGreedy
|
|
8
|
+
License: MIT
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import curses
|
|
12
|
+
import os
|
|
13
|
+
from listpick.pane.pane_utils import get_file_attributes, get_graph_string, escape_ansi
|
|
14
|
+
from listpick.pane.get_data import update_file_attributes
|
|
15
|
+
|
|
16
|
+
def left_start_pane(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
|
|
17
|
+
"""
|
|
18
|
+
Display file attributes in right pane.
|
|
19
|
+
"""
|
|
20
|
+
if test: return True
|
|
21
|
+
|
|
22
|
+
# Title
|
|
23
|
+
for i in range(h):
|
|
24
|
+
s = '*'*w
|
|
25
|
+
stdscr.addstr(y+i, x, s)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
stdscr.addstr(y, x, "+")
|
|
29
|
+
stdscr.addstr(y+h-1, x, "+")
|
|
30
|
+
stdscr.addstr(y, x+w-1, "+")
|
|
31
|
+
stdscr.addstr(y+h-1, x+w-1, "+")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
stdscr.addstr(y+1, x, f"{w},{h}")
|
|
35
|
+
|
|
36
|
+
return []
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def left_split_file_attributes(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
|
|
40
|
+
"""
|
|
41
|
+
Display file attributes in right pane.
|
|
42
|
+
"""
|
|
43
|
+
if test: return True
|
|
44
|
+
|
|
45
|
+
# Title
|
|
46
|
+
title = "File attributes"
|
|
47
|
+
if len(title) < w: title = f"{title:^{w}}"
|
|
48
|
+
stdscr.addstr(y, x,title[:w], curses.color_pair(state["colours_start"]+4) | curses.A_BOLD)
|
|
49
|
+
|
|
50
|
+
# Separator
|
|
51
|
+
for j in range(h):
|
|
52
|
+
stdscr.addstr(j+y, x+w-1, ' ', curses.color_pair(state["colours_start"]+16))
|
|
53
|
+
|
|
54
|
+
# Display pane count
|
|
55
|
+
pane_count = len(state["right_panes"])
|
|
56
|
+
pane_index = state["right_pane_index"]
|
|
57
|
+
if pane_count > 1:
|
|
58
|
+
s = f" {pane_index+1}/{pane_count} "
|
|
59
|
+
stdscr.addstr(y+h-1, x, s, curses.color_pair(state["colours_start"]+20))
|
|
60
|
+
|
|
61
|
+
# Filename/cursor cell value
|
|
62
|
+
stdscr.addstr(y+2, x+2, cell[:w-3])
|
|
63
|
+
|
|
64
|
+
attributes = get_file_attributes(cell)
|
|
65
|
+
for i, attr in enumerate(attributes):
|
|
66
|
+
stdscr.addstr(y+3+i, x+4, attr[:w-5])
|
|
67
|
+
|
|
68
|
+
return []
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def left_split_file_attributes_dynamic(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
|
|
72
|
+
"""
|
|
73
|
+
Display file attributes in right pane.
|
|
74
|
+
"""
|
|
75
|
+
if test: return True
|
|
76
|
+
|
|
77
|
+
# Title
|
|
78
|
+
title = "File attributes"
|
|
79
|
+
if len(title) < w: title = f"{title:^{w}}"
|
|
80
|
+
stdscr.addstr(y, x,title[:w], curses.color_pair(state["colours_start"]+4) | curses.A_BOLD)
|
|
81
|
+
|
|
82
|
+
# Separator
|
|
83
|
+
for j in range(h):
|
|
84
|
+
stdscr.addstr(j+y, x+w-1, ' ', curses.color_pair(state["colours_start"]+16))
|
|
85
|
+
|
|
86
|
+
# Display pane count
|
|
87
|
+
pane_count = len(state["right_panes"])
|
|
88
|
+
pane_index = state["right_pane_index"]
|
|
89
|
+
if pane_count > 1:
|
|
90
|
+
s = f" {pane_index+1}/{pane_count} "
|
|
91
|
+
stdscr.addstr(y+h-1, x, s, curses.color_pair(state["colours_start"]+20))
|
|
92
|
+
|
|
93
|
+
if len(state["indexed_items"]) == 0:
|
|
94
|
+
return []
|
|
95
|
+
|
|
96
|
+
# Filename/cursor cell value
|
|
97
|
+
stdscr.addstr(y+2, x+2, cell[:w-3])
|
|
98
|
+
|
|
99
|
+
# If the cursor-hovered file is different then reload the data
|
|
100
|
+
if data[1] != cell:
|
|
101
|
+
data[:] = update_file_attributes(data, state)
|
|
102
|
+
|
|
103
|
+
# attributes = get_file_attributes(cell)
|
|
104
|
+
if len(data) == 0: return []
|
|
105
|
+
attributes = data[0]
|
|
106
|
+
for i, attr in enumerate(attributes):
|
|
107
|
+
stdscr.addstr(y+3+i, x+4, attr[:w-5])
|
|
108
|
+
|
|
109
|
+
return []
|
|
110
|
+
|
|
111
|
+
def left_split_graph(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
|
|
112
|
+
"""
|
|
113
|
+
Display a graph of the data in right pane.
|
|
114
|
+
|
|
115
|
+
data[0] = x_vals
|
|
116
|
+
data[1] = y_vals
|
|
117
|
+
data[2] = id
|
|
118
|
+
"""
|
|
119
|
+
if test: return True
|
|
120
|
+
|
|
121
|
+
# Title
|
|
122
|
+
title = "Graph"
|
|
123
|
+
if len(title) < w: title = f"{title:^{w}}"
|
|
124
|
+
stdscr.addstr(y, x,title[:w], curses.color_pair(state["colours_start"]+4) | curses.A_BOLD)
|
|
125
|
+
|
|
126
|
+
# Separator
|
|
127
|
+
for j in range(h):
|
|
128
|
+
stdscr.addstr(j+y, x+w-1, ' ', curses.color_pair(state["colours_start"]+16))
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# Display pane count
|
|
132
|
+
pane_count = len(state["right_panes"])
|
|
133
|
+
pane_index = state["right_pane_index"]
|
|
134
|
+
if pane_count > 1:
|
|
135
|
+
s = f" {pane_index+1}/{pane_count} "
|
|
136
|
+
stdscr.addstr(y+h-1, x, s, curses.color_pair(state["colours_start"]+20))
|
|
137
|
+
|
|
138
|
+
try:
|
|
139
|
+
import plotille as plt
|
|
140
|
+
except:
|
|
141
|
+
s = f"No module named 'plotille'"
|
|
142
|
+
stdscr.addstr(y+2, x+1, s[:w-2])
|
|
143
|
+
return None
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
# x_vals, y_vals = list(range(100)), [x**2 for x in range(100)]
|
|
148
|
+
if data in [[], {}, None]:
|
|
149
|
+
return None
|
|
150
|
+
x_vals, y_vals = data[0], data[1]
|
|
151
|
+
graph_str = get_graph_string(x_vals, y_vals, width=w-3-10, height=h-3)
|
|
152
|
+
for i, s in enumerate(graph_str.split("\n")):
|
|
153
|
+
s = escape_ansi(s)
|
|
154
|
+
stdscr.addstr(y+2+i, x+1, s[:w-2])
|
|
155
|
+
|
|
156
|
+
return []
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def left_split_display_list(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
|
|
162
|
+
"""
|
|
163
|
+
data[0]:str = title
|
|
164
|
+
data[1]:list[str] = list of strings to display
|
|
165
|
+
"""
|
|
166
|
+
if test: return True
|
|
167
|
+
|
|
168
|
+
# Title
|
|
169
|
+
title = data[0]
|
|
170
|
+
if len(title) < w: title = f"{title:^{w}}"
|
|
171
|
+
stdscr.addstr(y, x,title[:w], curses.color_pair(state["colours_start"]+4) | curses.A_BOLD)
|
|
172
|
+
|
|
173
|
+
# Separator
|
|
174
|
+
for j in range(h):
|
|
175
|
+
stdscr.addstr(j+y, x+w-1, ' ', curses.color_pair(state["colours_start"]+16))
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# Display pane count
|
|
179
|
+
pane_count = len(state["right_panes"])
|
|
180
|
+
pane_index = state["right_pane_index"]
|
|
181
|
+
if pane_count > 1:
|
|
182
|
+
s = f" {pane_index+1}/{pane_count} "
|
|
183
|
+
stdscr.addstr(y+h-1, x, s, curses.color_pair(state["colours_start"]+20))
|
|
184
|
+
|
|
185
|
+
if data in [[], {}, None]:
|
|
186
|
+
return None
|
|
187
|
+
|
|
188
|
+
items = data[1]
|
|
189
|
+
number_to_display = min(len(items), h-3)
|
|
190
|
+
for i in range(number_to_display):
|
|
191
|
+
s = items[i]
|
|
192
|
+
stdscr.addstr(y+1+i, x+2, s[:w-2])
|
|
193
|
+
|
|
194
|
+
if number_to_display < len(items):
|
|
195
|
+
stdscr.addstr(y+1+number_to_display, x+2, f" ... {len(items)-number_to_display} more"[:w-2])
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
return []
|
listpick/pane/pane_functions.py
CHANGED
|
@@ -11,15 +11,14 @@ License: MIT
|
|
|
11
11
|
import curses
|
|
12
12
|
import os
|
|
13
13
|
from listpick.pane.pane_utils import get_file_attributes, get_graph_string, escape_ansi
|
|
14
|
+
from listpick.pane.get_data import update_file_attributes
|
|
14
15
|
|
|
15
|
-
def right_split_file_attributes(stdscr, x, y, w, h, state, row, cell,
|
|
16
|
+
def right_split_file_attributes(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
|
|
16
17
|
"""
|
|
17
18
|
Display file attributes in right pane.
|
|
18
19
|
"""
|
|
19
20
|
if test: return True
|
|
20
21
|
|
|
21
|
-
os.chdir(os.path.expanduser("~/Downloads/new"))
|
|
22
|
-
|
|
23
22
|
# Title
|
|
24
23
|
title = "File attributes"
|
|
25
24
|
if len(title) < w: title = f"{title:^{w}}"
|
|
@@ -45,7 +44,48 @@ def right_split_file_attributes(stdscr, x, y, w, h, state, row, cell, past_data:
|
|
|
45
44
|
|
|
46
45
|
return []
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
|
|
48
|
+
def right_split_file_attributes_dynamic(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
|
|
49
|
+
"""
|
|
50
|
+
Display file attributes in right pane.
|
|
51
|
+
"""
|
|
52
|
+
if test: return True
|
|
53
|
+
|
|
54
|
+
# Title
|
|
55
|
+
title = "File attributes"
|
|
56
|
+
if len(title) < w: title = f"{title:^{w}}"
|
|
57
|
+
stdscr.addstr(y, x,title[:w], curses.color_pair(state["colours_start"]+4) | curses.A_BOLD)
|
|
58
|
+
|
|
59
|
+
# Separator
|
|
60
|
+
for j in range(h):
|
|
61
|
+
stdscr.addstr(j+y, x, ' ', curses.color_pair(state["colours_start"]+16))
|
|
62
|
+
|
|
63
|
+
# Display pane count
|
|
64
|
+
pane_count = len(state["right_panes"])
|
|
65
|
+
pane_index = state["right_pane_index"]
|
|
66
|
+
if pane_count > 1:
|
|
67
|
+
s = f" {pane_index+1}/{pane_count} "
|
|
68
|
+
stdscr.addstr(y+h-1, x+w-len(s)-1, s, curses.color_pair(state["colours_start"]+20))
|
|
69
|
+
|
|
70
|
+
if len(state["indexed_items"]) == 0:
|
|
71
|
+
return []
|
|
72
|
+
|
|
73
|
+
# Filename/cursor cell value
|
|
74
|
+
stdscr.addstr(y+2, x+2, cell[:w-3])
|
|
75
|
+
|
|
76
|
+
# If the cursor-hovered file is different then reload the data
|
|
77
|
+
if data[1] != cell:
|
|
78
|
+
data[:] = update_file_attributes(data, state)
|
|
79
|
+
|
|
80
|
+
# attributes = get_file_attributes(cell)
|
|
81
|
+
if len(data) == 0: return []
|
|
82
|
+
attributes = data[0]
|
|
83
|
+
for i, attr in enumerate(attributes):
|
|
84
|
+
stdscr.addstr(y+3+i, x+4, attr[:w-5])
|
|
85
|
+
|
|
86
|
+
return []
|
|
87
|
+
|
|
88
|
+
def right_split_graph(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
|
|
49
89
|
"""
|
|
50
90
|
Display a graph of the data in right pane.
|
|
51
91
|
|
|
@@ -95,7 +135,7 @@ def right_split_graph(stdscr, x, y, w, h, state, row, cell, past_data: list = []
|
|
|
95
135
|
|
|
96
136
|
|
|
97
137
|
|
|
98
|
-
def right_split_display_list(stdscr, x, y, w, h, state, row, cell,
|
|
138
|
+
def right_split_display_list(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
|
|
99
139
|
"""
|
|
100
140
|
data[0]:str = title
|
|
101
141
|
data[1]:list[str] = list of strings to display
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/bin/python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
pane_functions.py
|
|
5
|
+
Functions which are run by a listpick Picker to display data in a pane.
|
|
6
|
+
|
|
7
|
+
Author: GrimAndGreedy
|
|
8
|
+
License: MIT
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import curses
|
|
12
|
+
import os
|
|
13
|
+
from listpick.pane.pane_utils import get_file_attributes, get_graph_string, escape_ansi
|
|
14
|
+
from listpick.pane.get_data import update_file_attributes
|
|
15
|
+
|
|
16
|
+
def right_split_file_attributes(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
|
|
17
|
+
"""
|
|
18
|
+
Display file attributes in right pane.
|
|
19
|
+
"""
|
|
20
|
+
if test: return True
|
|
21
|
+
|
|
22
|
+
# Title
|
|
23
|
+
title = "File attributes"
|
|
24
|
+
if len(title) < w: title = f"{title:^{w}}"
|
|
25
|
+
stdscr.addstr(y, x,title[:w], curses.color_pair(state["colours_start"]+4) | curses.A_BOLD)
|
|
26
|
+
|
|
27
|
+
# Separator
|
|
28
|
+
for j in range(h):
|
|
29
|
+
stdscr.addstr(j+y, x, ' ', curses.color_pair(state["colours_start"]+16))
|
|
30
|
+
|
|
31
|
+
# Display pane count
|
|
32
|
+
pane_count = len(state["right_panes"])
|
|
33
|
+
pane_index = state["right_pane_index"]
|
|
34
|
+
if pane_count > 1:
|
|
35
|
+
s = f" {pane_index+1}/{pane_count} "
|
|
36
|
+
stdscr.addstr(y+h-1, x+w-len(s)-1, s, curses.color_pair(state["colours_start"]+20))
|
|
37
|
+
|
|
38
|
+
# Filename/cursor cell value
|
|
39
|
+
stdscr.addstr(y+2, x+2, cell[:w-3])
|
|
40
|
+
|
|
41
|
+
attributes = get_file_attributes(cell)
|
|
42
|
+
for i, attr in enumerate(attributes):
|
|
43
|
+
stdscr.addstr(y+3+i, x+4, attr[:w-5])
|
|
44
|
+
|
|
45
|
+
return []
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def right_split_file_attributes_dynamic(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
|
|
49
|
+
"""
|
|
50
|
+
Display file attributes in right pane.
|
|
51
|
+
"""
|
|
52
|
+
if test: return True
|
|
53
|
+
|
|
54
|
+
# Title
|
|
55
|
+
title = "File attributes"
|
|
56
|
+
if len(title) < w: title = f"{title:^{w}}"
|
|
57
|
+
stdscr.addstr(y, x,title[:w], curses.color_pair(state["colours_start"]+4) | curses.A_BOLD)
|
|
58
|
+
|
|
59
|
+
# Separator
|
|
60
|
+
for j in range(h):
|
|
61
|
+
stdscr.addstr(j+y, x, ' ', curses.color_pair(state["colours_start"]+16))
|
|
62
|
+
|
|
63
|
+
# Display pane count
|
|
64
|
+
pane_count = len(state["right_panes"])
|
|
65
|
+
pane_index = state["right_pane_index"]
|
|
66
|
+
if pane_count > 1:
|
|
67
|
+
s = f" {pane_index+1}/{pane_count} "
|
|
68
|
+
stdscr.addstr(y+h-1, x+w-len(s)-1, s, curses.color_pair(state["colours_start"]+20))
|
|
69
|
+
|
|
70
|
+
if len(state["indexed_items"]) == 0:
|
|
71
|
+
return []
|
|
72
|
+
|
|
73
|
+
# Filename/cursor cell value
|
|
74
|
+
stdscr.addstr(y+2, x+2, cell[:w-3])
|
|
75
|
+
|
|
76
|
+
# If the cursor-hovered file is different then reload the data
|
|
77
|
+
if data[1] != cell:
|
|
78
|
+
data[:] = update_file_attributes(data, state)
|
|
79
|
+
|
|
80
|
+
# attributes = get_file_attributes(cell)
|
|
81
|
+
if len(data) == 0: return []
|
|
82
|
+
attributes = data[0]
|
|
83
|
+
for i, attr in enumerate(attributes):
|
|
84
|
+
stdscr.addstr(y+3+i, x+4, attr[:w-5])
|
|
85
|
+
|
|
86
|
+
return []
|
|
87
|
+
|
|
88
|
+
def right_split_graph(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
|
|
89
|
+
"""
|
|
90
|
+
Display a graph of the data in right pane.
|
|
91
|
+
|
|
92
|
+
data[0] = x_vals
|
|
93
|
+
data[1] = y_vals
|
|
94
|
+
data[2] = id
|
|
95
|
+
"""
|
|
96
|
+
if test: return True
|
|
97
|
+
|
|
98
|
+
# Title
|
|
99
|
+
title = "Graph"
|
|
100
|
+
if len(title) < w: title = f"{title:^{w}}"
|
|
101
|
+
stdscr.addstr(y, x,title[:w], curses.color_pair(state["colours_start"]+4) | curses.A_BOLD)
|
|
102
|
+
|
|
103
|
+
# Separator
|
|
104
|
+
for j in range(h):
|
|
105
|
+
stdscr.addstr(j+y, x, ' ', curses.color_pair(state["colours_start"]+16))
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
# Display pane count
|
|
109
|
+
pane_count = len(state["right_panes"])
|
|
110
|
+
pane_index = state["right_pane_index"]
|
|
111
|
+
if pane_count > 1:
|
|
112
|
+
s = f" {pane_index+1}/{pane_count} "
|
|
113
|
+
stdscr.addstr(y+h-1, x+w-len(s)-1, s, curses.color_pair(state["colours_start"]+20))
|
|
114
|
+
|
|
115
|
+
try:
|
|
116
|
+
import plotille as plt
|
|
117
|
+
except:
|
|
118
|
+
s = f"No module named 'plotille'"
|
|
119
|
+
stdscr.addstr(y+2, x+2, s[:w-2])
|
|
120
|
+
return None
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# x_vals, y_vals = list(range(100)), [x**2 for x in range(100)]
|
|
125
|
+
if data in [[], {}, None]:
|
|
126
|
+
return None
|
|
127
|
+
x_vals, y_vals = data[0], data[1]
|
|
128
|
+
graph_str = get_graph_string(x_vals, y_vals, width=w-3-10, height=h-3)
|
|
129
|
+
for i, s in enumerate(graph_str.split("\n")):
|
|
130
|
+
s = escape_ansi(s)
|
|
131
|
+
stdscr.addstr(y+2+i, x+2, s[:w-2])
|
|
132
|
+
|
|
133
|
+
return []
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def right_split_display_list(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
|
|
139
|
+
"""
|
|
140
|
+
data[0]:str = title
|
|
141
|
+
data[1]:list[str] = list of strings to display
|
|
142
|
+
"""
|
|
143
|
+
if test: return True
|
|
144
|
+
|
|
145
|
+
# Title
|
|
146
|
+
title = data[0]
|
|
147
|
+
if len(title) < w: title = f"{title:^{w}}"
|
|
148
|
+
stdscr.addstr(y, x,title[:w], curses.color_pair(state["colours_start"]+4) | curses.A_BOLD)
|
|
149
|
+
|
|
150
|
+
# Separator
|
|
151
|
+
for j in range(h):
|
|
152
|
+
stdscr.addstr(j+y, x, ' ', curses.color_pair(state["colours_start"]+16))
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
# Display pane count
|
|
156
|
+
pane_count = len(state["right_panes"])
|
|
157
|
+
pane_index = state["right_pane_index"]
|
|
158
|
+
if pane_count > 1:
|
|
159
|
+
s = f" {pane_index+1}/{pane_count} "
|
|
160
|
+
stdscr.addstr(y+h-1, x+w-len(s)-1, s, curses.color_pair(state["colours_start"]+20))
|
|
161
|
+
|
|
162
|
+
if data in [[], {}, None]:
|
|
163
|
+
return None
|
|
164
|
+
|
|
165
|
+
items = data[1]
|
|
166
|
+
number_to_display = min(len(items), h-3)
|
|
167
|
+
for i in range(number_to_display):
|
|
168
|
+
s = items[i]
|
|
169
|
+
stdscr.addstr(y+1+i, x+2, s[:w-2])
|
|
170
|
+
|
|
171
|
+
if number_to_display < len(items):
|
|
172
|
+
stdscr.addstr(y+1+number_to_display, x+2, f" ... {len(items)-number_to_display} more"[:w-2])
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
return []
|
listpick/pane/pane_utils.py
CHANGED
|
@@ -41,9 +41,9 @@ def get_graph_string(x_vals, y_vals, width=50, height=20, title=None, x_label=No
|
|
|
41
41
|
fig.ylabel = y_label
|
|
42
42
|
|
|
43
43
|
# Generate the ASCII art of the graph
|
|
44
|
-
|
|
44
|
+
graph_str = str(fig.show())
|
|
45
45
|
|
|
46
|
-
return
|
|
46
|
+
return graph_str
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
def get_file_attributes(filename):
|
|
@@ -83,6 +83,6 @@ def get_file_attributes(filename):
|
|
|
83
83
|
return attributes
|
|
84
84
|
|
|
85
85
|
except Exception as e:
|
|
86
|
-
print(f"An error occurred: {e}")
|
|
86
|
+
# print(f"An error occurred: {e}")
|
|
87
87
|
return []
|
|
88
88
|
|
listpick/ui/build_help.py
CHANGED
|
@@ -14,7 +14,7 @@ from listpick.utils import keycodes
|
|
|
14
14
|
|
|
15
15
|
logger = logging.getLogger('picker_log')
|
|
16
16
|
|
|
17
|
-
def build_help_rows(keys_dict: dict, debug: bool = False) -> list[list[str]]:
|
|
17
|
+
def build_help_rows(keys_dict: dict, macros: list, debug: bool = False) -> list[list[str]]:
|
|
18
18
|
""" Build help rows based on the keys_dict. """
|
|
19
19
|
|
|
20
20
|
logger.info(f"function: build_help_rows() (build_help.py)")
|
|
@@ -68,7 +68,7 @@ def build_help_rows(keys_dict: dict, debug: bool = False) -> list[list[str]]:
|
|
|
68
68
|
|
|
69
69
|
## Key descriptions
|
|
70
70
|
help_descriptions = {
|
|
71
|
-
"refresh": "Refresh
|
|
71
|
+
"refresh": "Refresh data.",
|
|
72
72
|
"help": "Open help.",
|
|
73
73
|
"exit": "Exit picker instance.",
|
|
74
74
|
"full_exit": "Immediate exit to terminal.",
|
|
@@ -117,9 +117,10 @@ def build_help_rows(keys_dict: dict, debug: bool = False) -> list[list[str]]:
|
|
|
117
117
|
"col_select_next": "Select next column.",
|
|
118
118
|
"col_select_prev": "Select previous column.",
|
|
119
119
|
"col_hide": "Hide column.",
|
|
120
|
-
"edit": "Edit cell.",
|
|
121
|
-
"
|
|
122
|
-
"
|
|
120
|
+
"edit": "Edit (editable) cell.",
|
|
121
|
+
"edit_nvim": "Edit (editable) cell(s) in nvim.",
|
|
122
|
+
"edit_picker": "Edit (editable) cell from options dialogue.",
|
|
123
|
+
"edit_ipython": "Drop to ipython shell with environment as `self`",
|
|
123
124
|
"copy": "Copy selections.",
|
|
124
125
|
"paste": "Paste into picker.",
|
|
125
126
|
"save": "Save selections.",
|
|
@@ -131,8 +132,8 @@ def build_help_rows(keys_dict: dict, debug: bool = False) -> list[list[str]]:
|
|
|
131
132
|
"undo": "Undo.",
|
|
132
133
|
"scroll_right": "Scroll right (5 chars).",
|
|
133
134
|
"scroll_left": "Scroll left (5 chars).",
|
|
134
|
-
"scroll_right_25":
|
|
135
|
-
"scroll_left_25":
|
|
135
|
+
"scroll_right_25": "Scroll right (25 chars).",
|
|
136
|
+
"scroll_left_25": "Scroll left (25 chars).",
|
|
136
137
|
"scroll_far_right": "Scroll to the end of the column set.",
|
|
137
138
|
"scroll_far_left": "Scroll to the left home.",
|
|
138
139
|
"add_column_before": "Insert column before cursor.",
|
|
@@ -145,17 +146,19 @@ def build_help_rows(keys_dict: dict, debug: bool = False) -> list[list[str]]:
|
|
|
145
146
|
"sheet_next": "Go to the next sheet.",
|
|
146
147
|
"sheet_prev": "Go to the previous sheet.",
|
|
147
148
|
"toggle_right_pane": "Toggle the right pane",
|
|
148
|
-
"cycle_right_pane": "Cycle through right
|
|
149
|
+
"cycle_right_pane": "Cycle through right pane views",
|
|
150
|
+
"toggle_left_pane": "Toggle the left pane",
|
|
151
|
+
"cycle_left_pane": "Cycle through left pane views",
|
|
149
152
|
}
|
|
150
153
|
sections = {
|
|
151
154
|
"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_right_25", "scroll_left_25", "scroll_far_right", "scroll_far_left" ],
|
|
152
155
|
"Selection:": [ "toggle_select", "select_all", "select_none", "visual_selection_toggle", "visual_deselection_toggle", "enter" ],
|
|
153
|
-
"UI:": [ "toggle_footer", "redraw_screen", "decrease_lines_per_page", "increase_lines_per_page", "increase_column_width", "decrease_column_width", "notification_toggle", "toggle_right_pane", "cycle_right_pane"],
|
|
156
|
+
"UI:": [ "toggle_footer", "redraw_screen", "decrease_lines_per_page", "increase_lines_per_page", "increase_column_width", "decrease_column_width", "notification_toggle", "toggle_right_pane", "cycle_right_pane", "toggle_left_pane", "cycle_left_pane"],
|
|
154
157
|
"Sort:": [ "cycle_sort_method", "cycle_sort_method_reverse", "cycle_sort_order", ] ,
|
|
155
|
-
"Data manipulation:": [ "delete", "delete_column", "edit", "edit_picker", "edit_ipython", "add_column_before", "add_column_after", "add_row_before", "add_row_after"],
|
|
156
|
-
"Filter and
|
|
158
|
+
"Data manipulation:": [ "delete", "delete_column", "edit", "edit_nvim", "edit_picker", "edit_ipython", "add_column_before", "add_column_after", "add_row_before", "add_row_after"],
|
|
159
|
+
"Filter and search:": [ "filter_input", "search_input", "continue_search_forward", "continue_search_backward", ] ,
|
|
157
160
|
"Settings:": [ "settings_input", "settings_options" ],
|
|
158
|
-
"
|
|
161
|
+
"Options and modes:": [ "opts_input", "opts_select", "mode_next", "mode_prev", "pipe_input", "reset_opts", "col_select", "col_select_next", "col_select_prev", "col_hide" ],
|
|
159
162
|
"Save, load, copy and paste:": [ "save", "load", "open", "copy", "paste" ],
|
|
160
163
|
"Misc:": [ "redo", "undo", "refresh", "help", "exit", "full_exit", "move_column_left", "move_column_right" ],
|
|
161
164
|
}
|
|
@@ -170,6 +173,8 @@ def build_help_rows(keys_dict: dict, debug: bool = False) -> list[list[str]]:
|
|
|
170
173
|
if not found:
|
|
171
174
|
sections["Misc:"].append(key)
|
|
172
175
|
|
|
176
|
+
|
|
177
|
+
|
|
173
178
|
items = []
|
|
174
179
|
for section_name, section_operations in sections.items():
|
|
175
180
|
section_rows = []
|
|
@@ -205,6 +210,26 @@ def build_help_rows(keys_dict: dict, debug: bool = False) -> list[list[str]]:
|
|
|
205
210
|
items += section_rows
|
|
206
211
|
items.append(["",""])
|
|
207
212
|
|
|
213
|
+
if macros:
|
|
214
|
+
items.append([f" Macros:", ""])
|
|
215
|
+
for macro in macros:
|
|
216
|
+
keys = []
|
|
217
|
+
for key in macro["keys"]:
|
|
218
|
+
if key in special_keys:
|
|
219
|
+
keys.append(special_keys[key])
|
|
220
|
+
else:
|
|
221
|
+
try:
|
|
222
|
+
keys.append(chr(int(key)))
|
|
223
|
+
except Exception as e:
|
|
224
|
+
keys.append(f"keycode={key}")
|
|
225
|
+
if debug: print(f"Error chr({key}): {e}")
|
|
226
|
+
|
|
227
|
+
row = [f" {str(keys)[1:-1]}", macro["description"]]
|
|
228
|
+
items.append(row)
|
|
229
|
+
items.append(["",""])
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
208
233
|
if debug:
|
|
209
234
|
for operation in keys_dict:
|
|
210
235
|
if operation not in help_descriptions:
|
|
File without changes
|
listpick/ui/footer.py
CHANGED
|
@@ -160,7 +160,7 @@ class StandardFooter(Footer):
|
|
|
160
160
|
if state["footer_string"]:
|
|
161
161
|
footer_string_width = min(w-1, len(state["footer_string"])+2)
|
|
162
162
|
|
|
163
|
-
disp_string = f"{state[
|
|
163
|
+
disp_string = f"{state['footer_string'][:footer_string_width]}"
|
|
164
164
|
disp_string = f" {disp_string:>{footer_string_width-2}} "
|
|
165
165
|
self.stdscr.addstr(self.footer_string_y, w-footer_string_width-1, " "*footer_string_width, curses.color_pair(self.colours_start+24))
|
|
166
166
|
self.stdscr.addstr(self.footer_string_y, w-footer_string_width-1, f"{disp_string}", curses.color_pair(self.colours_start+24))
|
|
@@ -259,7 +259,7 @@ class CompactFooter(Footer):
|
|
|
259
259
|
if state["footer_string"]:
|
|
260
260
|
footer_string_width = min(w-1, len(state["footer_string"])+2)
|
|
261
261
|
|
|
262
|
-
disp_string = f"{state[
|
|
262
|
+
disp_string = f"{state['footer_string'][:footer_string_width]}"
|
|
263
263
|
disp_string = f" {disp_string:>{footer_string_width-2}} "
|
|
264
264
|
self.stdscr.addstr(h - 1, w-footer_string_width-1, " "*footer_string_width, curses.color_pair(self.colours_start+24))
|
|
265
265
|
self.stdscr.addstr(h - 1, w-footer_string_width-1, f"{disp_string}", curses.color_pair(self.colours_start+24))
|
|
@@ -318,7 +318,7 @@ class NoFooter(Footer):
|
|
|
318
318
|
|
|
319
319
|
if state["footer_string"]:
|
|
320
320
|
footer_string_width = min(w-1, len(state["footer_string"])+2)
|
|
321
|
-
disp_string = f"{state[
|
|
321
|
+
disp_string = f"{state['footer_string'][:footer_string_width]}"
|
|
322
322
|
disp_string = f" {disp_string:>{footer_string_width-2}} "
|
|
323
323
|
self.stdscr.addstr(h - 1, w-footer_string_width-1, " "*footer_string_width, curses.color_pair(self.colours_start+24))
|
|
324
324
|
self.stdscr.addstr(h - 1, w-footer_string_width-1, f"{disp_string}", curses.color_pair(self.colours_start+24))
|
listpick/ui/input_field.py
CHANGED
|
@@ -16,27 +16,9 @@ from datetime import datetime
|
|
|
16
16
|
import logging
|
|
17
17
|
|
|
18
18
|
logger = logging.getLogger('picker_log')
|
|
19
|
-
import select
|
|
20
|
-
import tty
|
|
21
19
|
from listpick.utils.user_input import get_char, open_tty
|
|
22
20
|
from listpick.utils import keycodes
|
|
23
21
|
|
|
24
|
-
# def open_tty():
|
|
25
|
-
# """ Return a file descriptor for the tty that we are opening"""
|
|
26
|
-
# tty_fd = os.open('/dev/tty', os.O_RDONLY)
|
|
27
|
-
# tty.setraw(tty_fd)
|
|
28
|
-
# return tty_fd
|
|
29
|
-
#
|
|
30
|
-
# def get_char(tty_fd, timeout: float = 0.2) -> int:
|
|
31
|
-
# """ Get character from a tty_fd with a timeout. """
|
|
32
|
-
# rlist, _, _ = select.select([tty_fd], [], [], timeout)
|
|
33
|
-
# if rlist:
|
|
34
|
-
# # key = ord(tty_fd.read(1))
|
|
35
|
-
# key = ord(os.read(tty_fd, 1))
|
|
36
|
-
# else:
|
|
37
|
-
# key = -1
|
|
38
|
-
# return key
|
|
39
|
-
|
|
40
22
|
def input_field(
|
|
41
23
|
stdscr: curses.window,
|
|
42
24
|
usrtxt:str="",
|
|
@@ -126,7 +108,7 @@ def input_field(
|
|
|
126
108
|
offscreen_x, offscreen_y = False, False
|
|
127
109
|
orig_x, orig_y = x, y
|
|
128
110
|
|
|
129
|
-
tty_fd = open_tty()
|
|
111
|
+
tty_fd, saved_terminal_state = open_tty()
|
|
130
112
|
|
|
131
113
|
# Input field loop
|
|
132
114
|
while True:
|
|
@@ -211,7 +193,6 @@ def input_field(
|
|
|
211
193
|
match_word, left_ptr, right_ptr = get_partially_complete_word(usrtxt, cursor, [" ", "/", "="])
|
|
212
194
|
|
|
213
195
|
if match_word in completions:
|
|
214
|
-
# os.system(f"notify-send '{completions[0]}'")
|
|
215
196
|
index = completions.index(match_word)
|
|
216
197
|
if index == len(completions) - 1: index = -1
|
|
217
198
|
completions_disp_str = str(completions[index:])[:max_field_length]
|