vappman 0.6__py3-none-any.whl → 0.8__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.
- vappman/PowerWindow.py +1 -1
- vappman/main.py +197 -40
- {vappman-0.6.dist-info → vappman-0.8.dist-info}/METADATA +18 -7
- vappman-0.8.dist-info/RECORD +9 -0
- {vappman-0.6.dist-info → vappman-0.8.dist-info}/WHEEL +1 -1
- vappman-0.6.dist-info/RECORD +0 -9
- {vappman-0.6.dist-info → vappman-0.8.dist-info}/LICENSE +0 -0
- {vappman-0.6.dist-info → vappman-0.8.dist-info}/entry_points.txt +0 -0
- {vappman-0.6.dist-info → vappman-0.8.dist-info}/top_level.txt +0 -0
vappman/PowerWindow.py
CHANGED
|
@@ -588,7 +588,7 @@ class Window:
|
|
|
588
588
|
def alert(self, title='ALERT', message='', height=1, width=80):
|
|
589
589
|
"""Alert box"""
|
|
590
590
|
def mod_key(key):
|
|
591
|
-
return 7 if key
|
|
591
|
+
return 7 if key in (10, curses.KEY_ENTER) else key
|
|
592
592
|
|
|
593
593
|
# need 3 extra cols for rectangle (so we don't draw in southeast corner)
|
|
594
594
|
# and 3 rows (top/prompt/bottom)
|
vappman/main.py
CHANGED
|
@@ -6,7 +6,7 @@ Interactive, visual thin layer atop appman
|
|
|
6
6
|
# pylint: disable=broad-exception-caught,consider-using-with
|
|
7
7
|
# pylint: disable=too-many-instance-attributes,too-many-branches
|
|
8
8
|
# pylint: disable=too-many-return-statements,too-many-statements
|
|
9
|
-
|
|
9
|
+
# pylint: disable=consider-using-in,too-many-nested-blocks
|
|
10
10
|
# pylint: disable=wrong-import-position,disable=wrong-import-order
|
|
11
11
|
# import VirtEnv
|
|
12
12
|
# VirtEnv.ensure_venv(__name__)
|
|
@@ -14,13 +14,11 @@ Interactive, visual thin layer atop appman
|
|
|
14
14
|
import os
|
|
15
15
|
import sys
|
|
16
16
|
import re
|
|
17
|
+
import glob
|
|
17
18
|
import shutil
|
|
18
19
|
import subprocess
|
|
19
20
|
import traceback
|
|
20
|
-
import copy
|
|
21
|
-
import shutil
|
|
22
21
|
import curses as cs
|
|
23
|
-
from types import SimpleNamespace
|
|
24
22
|
from vappman.PowerWindow import Window, OptionSpinner
|
|
25
23
|
|
|
26
24
|
|
|
@@ -37,9 +35,10 @@ class Vappman:
|
|
|
37
35
|
spin.add_key('help_mode', '? - toggle help screen', vals=[False, True])
|
|
38
36
|
|
|
39
37
|
# EXPAND
|
|
40
|
-
other = '
|
|
38
|
+
other = 'airtbou/qxscU'
|
|
41
39
|
other_keys = set(ord(x) for x in other)
|
|
42
40
|
other_keys.add(cs.KEY_ENTER)
|
|
41
|
+
other_keys.add(27) # ESCAPE
|
|
43
42
|
other_keys.add(10) # another form of ENTER
|
|
44
43
|
self.opts = spin.default_obj
|
|
45
44
|
|
|
@@ -51,6 +50,9 @@ class Vappman:
|
|
|
51
50
|
self.check_preqreqs()
|
|
52
51
|
self.apps = self.cmd_dict('appman list')
|
|
53
52
|
self.installs = self.get_installed() # dict keyed by app
|
|
53
|
+
self.appman_dir = self.get_appman_dir()
|
|
54
|
+
self.dot_desktop_dir = self.get_dot_desktop_dir()
|
|
55
|
+
self.terminal_emulator = None
|
|
54
56
|
self.win = Window(head_line=True, body_rows=len(self.apps)+20, head_rows=10,
|
|
55
57
|
keys=spin.keys ^ other_keys, mod_pick=self.mod_pick)
|
|
56
58
|
|
|
@@ -96,6 +98,43 @@ class Vappman:
|
|
|
96
98
|
rv = self.cmd_dict('appman files --byname')
|
|
97
99
|
return rv
|
|
98
100
|
|
|
101
|
+
@staticmethod
|
|
102
|
+
def get_appman_dir():
|
|
103
|
+
""" Try to figure out where the apps are stored. """
|
|
104
|
+
|
|
105
|
+
appman_dir = None, None
|
|
106
|
+
try:
|
|
107
|
+
config_dir = os.getenv('XDG_CONFIG_HOME')
|
|
108
|
+
if not config_dir:
|
|
109
|
+
config_dir = os.path.join(os.getenv('HOME'), '.config')
|
|
110
|
+
config_file = os.path.join(config_dir, 'appman', 'appman-config')
|
|
111
|
+
with open(config_file, 'r', encoding='utf-8') as fh:
|
|
112
|
+
appman_dir = fh.read().strip()
|
|
113
|
+
appman_dir = os.path.join(os.getenv('HOME'), appman_dir)
|
|
114
|
+
os.listdir(appman_dir)
|
|
115
|
+
return appman_dir
|
|
116
|
+
except Exception as exc:
|
|
117
|
+
print(f'NOTE: cannot get appman dir; tried below {appman_dir!r}; {exc}')
|
|
118
|
+
print(' Check if contents of ~/config/appman/appman-config'
|
|
119
|
+
+ ' is the subdir of $HOME w your appman apps')
|
|
120
|
+
return None
|
|
121
|
+
|
|
122
|
+
@staticmethod
|
|
123
|
+
def get_dot_desktop_dir():
|
|
124
|
+
""" Try to figure out where the .desktop files are stored. """
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
data_dir = os.getenv('XDG_DATA_HOME')
|
|
128
|
+
if not data_dir:
|
|
129
|
+
data_dir = os.path.join(os.getenv('HOME'), '.local', 'share')
|
|
130
|
+
dot_dir = os.path.join(data_dir, 'applications')
|
|
131
|
+
os.listdir(dot_dir)
|
|
132
|
+
return dot_dir
|
|
133
|
+
except Exception as exc:
|
|
134
|
+
print(f'NOTE: cannot get .desktop dir; tried below {data_dir!r}; {exc}')
|
|
135
|
+
print(' Check if contents of ~/.local/share/applications for .desktop files')
|
|
136
|
+
return None
|
|
137
|
+
|
|
99
138
|
def main_loop(self):
|
|
100
139
|
""" TBD """
|
|
101
140
|
|
|
@@ -108,18 +147,20 @@ class Vappman:
|
|
|
108
147
|
# EXPAND
|
|
109
148
|
lines = [
|
|
110
149
|
'ALWAYS AVAILABLE:',
|
|
111
|
-
' q - quit program (CTL-C disabled)',
|
|
150
|
+
' q or x - quit program (CTL-C disabled)',
|
|
112
151
|
' a - about (more info about app)',
|
|
113
152
|
' s - sync (update appman itself)',
|
|
114
153
|
' c - clean (remove unneeded files/folters)',
|
|
115
154
|
' U - update ALL installed apps',
|
|
116
155
|
' / - filter apps',
|
|
117
156
|
' ENTER = install, remove, or return from help',
|
|
157
|
+
' ESC = clear filter and jump to top',
|
|
118
158
|
'CONTEXT SENSITIVE:',
|
|
119
159
|
' i - install uninstalled app',
|
|
120
160
|
' r - remove installed app',
|
|
121
161
|
' b - backup installed app',
|
|
122
162
|
' u - update installed app',
|
|
163
|
+
' t - test by opening a terminal emulator and launching the app'
|
|
123
164
|
' o - overwrite app from its backup',
|
|
124
165
|
|
|
125
166
|
]
|
|
@@ -128,6 +169,12 @@ class Vappman:
|
|
|
128
169
|
else:
|
|
129
170
|
def wanted(line):
|
|
130
171
|
return not self.filter or self.filter.search(line)
|
|
172
|
+
def version_of(app):
|
|
173
|
+
# ◆ krita | 5.2.2 | appimage-type2 | 355 MiB
|
|
174
|
+
fields = self.installs[app].split('|')
|
|
175
|
+
if len(fields) >= 2:
|
|
176
|
+
return fields[1].strip()
|
|
177
|
+
return '?version?'
|
|
131
178
|
|
|
132
179
|
# self.win.set_pick_mode(self.opts.pick_mode, self.opts.pick_size)
|
|
133
180
|
self.win.set_pick_mode(True)
|
|
@@ -135,11 +182,11 @@ class Vappman:
|
|
|
135
182
|
for app, line in self.installs.items():
|
|
136
183
|
if app in self.apps:
|
|
137
184
|
line = self.apps[app]
|
|
138
|
-
if wanted(line):
|
|
139
|
-
line = '✔✔✔
|
|
185
|
+
if wanted(line[2:]):
|
|
186
|
+
line = f'✔✔✔ {app} [{version_of(app)}] :{line.split(':', maxsplit=1)[1]}'
|
|
140
187
|
self.win.add_body(line)
|
|
141
188
|
for app, line in self.apps.items():
|
|
142
|
-
if app not in self.installs and wanted(line):
|
|
189
|
+
if app not in self.installs and wanted(line[2:]):
|
|
143
190
|
self.win.add_body(line)
|
|
144
191
|
self.win.render()
|
|
145
192
|
|
|
@@ -149,15 +196,17 @@ class Vappman:
|
|
|
149
196
|
def get_keys_line(self):
|
|
150
197
|
""" TBD """
|
|
151
198
|
# EXPAND
|
|
152
|
-
|
|
153
|
-
line = 'KEYS:'
|
|
199
|
+
line = ''
|
|
154
200
|
for key, verb in self.actions.items():
|
|
155
|
-
|
|
201
|
+
if key[0] == verb[0]:
|
|
202
|
+
line += f' {verb}'
|
|
203
|
+
else:
|
|
204
|
+
line += f' {key}:{verb}'
|
|
156
205
|
# or EXPAND
|
|
157
|
-
line += f' ?:help
|
|
206
|
+
line += f' ?:help quit about sync clean Upd /{self.prev_filter} '
|
|
158
207
|
# for action in self.actions:
|
|
159
208
|
# line += f' {action[0]}:{action}'
|
|
160
|
-
return line
|
|
209
|
+
return line[1:]
|
|
161
210
|
|
|
162
211
|
def get_actions(self, line):
|
|
163
212
|
""" Determine the type of the current line and available commands."""
|
|
@@ -173,6 +222,7 @@ class Vappman:
|
|
|
173
222
|
actions['b'] = 'bkup'
|
|
174
223
|
actions['o'] = 'overwr'
|
|
175
224
|
actions['u'] = 'upd'
|
|
225
|
+
actions['t'] = 'test'
|
|
176
226
|
else:
|
|
177
227
|
actions['i'] = 'install'
|
|
178
228
|
|
|
@@ -185,30 +235,122 @@ class Vappman:
|
|
|
185
235
|
"""
|
|
186
236
|
this = Vappman.singleton
|
|
187
237
|
this.pick_app, this.actions = this.get_actions(line)
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
238
|
+
header = this.get_keys_line()
|
|
239
|
+
# ASSUME line ends in /....
|
|
240
|
+
parts = header.split('/', maxsplit=1)
|
|
241
|
+
wds = parts[0].split()
|
|
242
|
+
this.win.head.pad.move(0, 0)
|
|
243
|
+
for wd in wds:
|
|
244
|
+
if wd:
|
|
245
|
+
this.win.add_header(wd[0], attr=cs.A_BOLD|cs.A_UNDERLINE, resume=True)
|
|
246
|
+
if wd[1:]:
|
|
247
|
+
this.win.add_header(wd[1:] + ' ', resume=True)
|
|
248
|
+
|
|
249
|
+
this.win.add_header('/', attr=cs.A_BOLD+cs.A_UNDERLINE, resume=True)
|
|
250
|
+
if len(parts) > 1 and parts[1]:
|
|
251
|
+
this.win.add_header(f'{parts[1]}', resume=True)
|
|
252
|
+
_, col = this.win.head.pad.getyx()
|
|
253
|
+
pad = ' ' * (this.win.get_pad_width()-col)
|
|
254
|
+
this.win.add_header(pad, resume=True)
|
|
191
255
|
return line
|
|
192
|
-
|
|
193
|
-
# suffix = ''
|
|
194
|
-
# for action in actions:
|
|
195
|
-
# suffix += f' {action[0]}:{action}'
|
|
196
|
-
# block_char = "\u2588"
|
|
197
|
-
# suffix = f'{block_char*5} {suffix}'
|
|
198
|
-
# over = len(line) + len(suffix) - this.win.get_pad_width()
|
|
199
|
-
# if over < 0:
|
|
200
|
-
# line += ' '*(-over)
|
|
201
|
-
# elif over > 0:
|
|
202
|
-
# line = line[0:-over]
|
|
203
|
-
|
|
204
|
-
# return line + suffix
|
|
256
|
+
|
|
205
257
|
def run_appman(self, cmd):
|
|
258
|
+
""" Run a 'appman' command """
|
|
206
259
|
Window.stop_curses()
|
|
207
260
|
os.system(f'clear; stty sane; {cmd};'
|
|
208
|
-
+ ' /bin/echo -e "\n\n===== Press ENTER for menu ====> \c"; read FOO')
|
|
261
|
+
+ r' /bin/echo -e "\n\n===== Press ENTER for menu ====> \c"; read FOO')
|
|
209
262
|
self.installs = self.get_installed()
|
|
210
263
|
Window._start_curses()
|
|
211
264
|
|
|
265
|
+
@staticmethod
|
|
266
|
+
def launch_desktop_file(desktop_file_path):
|
|
267
|
+
""" Launch the .desktop file using xdg-open in a detached process """
|
|
268
|
+
try:
|
|
269
|
+
trial = ['xdg-open', desktop_file_path]
|
|
270
|
+
subprocess.Popen(trial,
|
|
271
|
+
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, close_fds=True)
|
|
272
|
+
return None
|
|
273
|
+
except Exception:
|
|
274
|
+
return trial
|
|
275
|
+
|
|
276
|
+
def launch_in_terminal(self, executable):
|
|
277
|
+
""" Find a terminal emulator"""
|
|
278
|
+
if not self.terminal_emulator:
|
|
279
|
+
maybes = [
|
|
280
|
+
[ 'konsole', '--noclose', '-e', '"{command}"'],
|
|
281
|
+
[ 'gnome-terminal', '--', 'bash', '-c', '"{command}"; exec bash' ],
|
|
282
|
+
[ 'xfce4-terminal', '--hold', '--command="{command}"' ],
|
|
283
|
+
[ 'lxterminal', '-e', """bash -c '"{command}"; echo; read -p "Press Enter to close..."'"""],
|
|
284
|
+
# [ terminator', ],
|
|
285
|
+
# [ alacritty', ],
|
|
286
|
+
# [ termite', ],
|
|
287
|
+
# [ urxvt', ],
|
|
288
|
+
# [ sakura', ],
|
|
289
|
+
# [ tilix', ],
|
|
290
|
+
# [ kitty', ],
|
|
291
|
+
# [ hyper', ],
|
|
292
|
+
# [ guake', ],
|
|
293
|
+
# [ yakuake', ],
|
|
294
|
+
]
|
|
295
|
+
for maybe in maybes:
|
|
296
|
+
if shutil.which(maybe[0]):
|
|
297
|
+
self.terminal_emulator = maybe
|
|
298
|
+
break
|
|
299
|
+
if self.terminal_emulator:
|
|
300
|
+
try:
|
|
301
|
+
trial = []
|
|
302
|
+
for wd in self.terminal_emulator:
|
|
303
|
+
trial.append(wd.replace('{command}', executable))
|
|
304
|
+
subprocess.Popen(trial)
|
|
305
|
+
return None
|
|
306
|
+
except Exception:
|
|
307
|
+
return trial
|
|
308
|
+
return trial
|
|
309
|
+
|
|
310
|
+
def launch_app(self, app):
|
|
311
|
+
""" Try to run an app."""
|
|
312
|
+
# First dig out where it might be installed as a .desktop file
|
|
313
|
+
# by searching the 'remove' script
|
|
314
|
+
def get_unique_words_from_file(file_path):
|
|
315
|
+
seen_words = set()
|
|
316
|
+
with open(file_path, 'r', encoding='utf-8') as file:
|
|
317
|
+
for line in file:
|
|
318
|
+
line_words = line.split()
|
|
319
|
+
for word in line_words:
|
|
320
|
+
if word not in seen_words:
|
|
321
|
+
seen_words.add(word)
|
|
322
|
+
return seen_words
|
|
323
|
+
|
|
324
|
+
failures = []
|
|
325
|
+
executables = []
|
|
326
|
+
try:
|
|
327
|
+
for globname in get_unique_words_from_file(
|
|
328
|
+
os.path.join(self.appman_dir, app, 'remove')):
|
|
329
|
+
results = glob.glob(globname)
|
|
330
|
+
if '/share/applications/AM-ZZZ' in globname:
|
|
331
|
+
for result in results:
|
|
332
|
+
if result.endswith('.desktop'):
|
|
333
|
+
failure = self.launch_desktop_file(result)
|
|
334
|
+
if failure:
|
|
335
|
+
failures.append(' '.join(failure))
|
|
336
|
+
return
|
|
337
|
+
elif '/.local/bin/' in globname:
|
|
338
|
+
for result in results:
|
|
339
|
+
if os.access(result, os.X_OK):
|
|
340
|
+
executables.append(result)
|
|
341
|
+
for executable in executables:
|
|
342
|
+
failure = self.launch_in_terminal(executable)
|
|
343
|
+
if failure:
|
|
344
|
+
failures.append(' '.join(failure))
|
|
345
|
+
return
|
|
346
|
+
except Exception as exc:
|
|
347
|
+
failures += f'cannot find .desktop/executable to run [{exc}]'
|
|
348
|
+
if failures:
|
|
349
|
+
message = ' '.join([f'Cannot launch {app}'] + failures)
|
|
350
|
+
self.win.alert(message=message)
|
|
351
|
+
|
|
352
|
+
self.launch_app(self.pick_app)
|
|
353
|
+
|
|
212
354
|
def do_key(self, key):
|
|
213
355
|
""" TBD """
|
|
214
356
|
if not key:
|
|
@@ -217,16 +359,22 @@ class Vappman:
|
|
|
217
359
|
if self.opts.help_mode:
|
|
218
360
|
self.opts.help_mode = False
|
|
219
361
|
return True
|
|
220
|
-
|
|
221
|
-
key = ord('r') #
|
|
362
|
+
if self.pick_is_installed:
|
|
363
|
+
key = ord('r') # remove installed app
|
|
222
364
|
else:
|
|
223
365
|
key = ord('i') # install uninstalled app
|
|
224
366
|
|
|
225
367
|
if key in self.spin.keys:
|
|
226
368
|
value = self.spin.do_key(key, self.win)
|
|
227
369
|
return value
|
|
228
|
-
|
|
229
|
-
if key ==
|
|
370
|
+
|
|
371
|
+
if key == 27: # ESCAPE
|
|
372
|
+
self.prev_filter = ''
|
|
373
|
+
self.filter = None
|
|
374
|
+
self.win.pick_pos = 0
|
|
375
|
+
return None
|
|
376
|
+
|
|
377
|
+
if key in (ord('q'), ord('x')):
|
|
230
378
|
self.win.stop_curses()
|
|
231
379
|
os.system('clear; stty sane')
|
|
232
380
|
sys.exit(0)
|
|
@@ -239,6 +387,10 @@ class Vappman:
|
|
|
239
387
|
self.run_appman(f'appman remove {self.pick_app}')
|
|
240
388
|
return None
|
|
241
389
|
|
|
390
|
+
if key == ord('t') and self.pick_is_installed:
|
|
391
|
+
self.launch_app(self.pick_app)
|
|
392
|
+
return None
|
|
393
|
+
|
|
242
394
|
if key == ord('s'):
|
|
243
395
|
self.run_appman('appman sync')
|
|
244
396
|
if key == ord('c'):
|
|
@@ -252,11 +404,12 @@ class Vappman:
|
|
|
252
404
|
if key == ord('u'):
|
|
253
405
|
self.run_appman(f'appman update {self.pick_app}')
|
|
254
406
|
if key == ord('U'):
|
|
255
|
-
self.run_appman(
|
|
407
|
+
self.run_appman('appman update')
|
|
256
408
|
# EXPAND
|
|
257
409
|
|
|
258
410
|
if key == ord('/'):
|
|
259
411
|
# pylint: disable=protected-access
|
|
412
|
+
start_filter = self.prev_filter
|
|
260
413
|
|
|
261
414
|
prefix = ''
|
|
262
415
|
while True:
|
|
@@ -266,18 +419,22 @@ class Vappman:
|
|
|
266
419
|
pattern.strip()
|
|
267
420
|
if not pattern:
|
|
268
421
|
self.filter = None
|
|
269
|
-
|
|
422
|
+
break
|
|
270
423
|
|
|
271
424
|
try:
|
|
272
425
|
if re.match(r'^[\-\w\s]*$', pattern):
|
|
273
426
|
words = pattern.split()
|
|
274
|
-
self.filter = re.compile(r'\b' + r'
|
|
275
|
-
|
|
427
|
+
self.filter = re.compile(r'\b' + r'(|.*\b)'.join(words), re.IGNORECASE)
|
|
428
|
+
break
|
|
276
429
|
self.filter = re.compile(pattern, re.IGNORECASE)
|
|
277
|
-
|
|
430
|
+
break
|
|
278
431
|
except Exception:
|
|
279
432
|
prefix = 'Bad regex: '
|
|
280
433
|
|
|
434
|
+
if start_filter != self.prev_filter:
|
|
435
|
+
# when filter changes, move to top
|
|
436
|
+
self.win.pick_pos = 0
|
|
437
|
+
|
|
281
438
|
return None
|
|
282
439
|
return None
|
|
283
440
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: vappman
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8
|
|
4
4
|
Summary: A visual wrapper for appman
|
|
5
5
|
Author-email: Joe Defen <joedef@google.com>
|
|
6
6
|
License: MIT
|
|
@@ -41,7 +41,7 @@ But it does NOT cover:
|
|
|
41
41
|
* (-v) version of appman
|
|
42
42
|
* --force-latest to get the most recent stable release AND
|
|
43
43
|
all other options and unmentioned commands.
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
## Usage
|
|
46
46
|
* Run `vappman` from the command line.
|
|
47
47
|
* It presents some keys available on the top line.
|
|
@@ -56,13 +56,20 @@ But it does NOT cover:
|
|
|
56
56
|
* Installed apps have prefix '✔✔✔' (i.e., three checks).
|
|
57
57
|
* Uninstalled apps have prefix '◆' (i.e., a solid diamond).
|
|
58
58
|
* Enter `/` to enter a "filter" for installed/uninstalled apps, if you wish.
|
|
59
|
-
* If you enter plain ole "words", then those words must match
|
|
60
|
-
of the apps
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
* If you enter plain ole "words", then those words must match:
|
|
60
|
+
* the start of words on the apps line (in order, but not contiguously) and/or
|
|
61
|
+
* the start of the remainder of the previous word match
|
|
62
|
+
(i.e., `/bit fight` matches `bitfighter`).
|
|
63
|
+
* Or you can enter an regular expression acceptable to python; e.g.,
|
|
64
|
+
* `^` matches the line starting with the app name
|
|
65
|
+
* `\b` matches a word boundary; and so forth.
|
|
66
|
+
* NOTES:
|
|
67
|
+
* `ESC` clears the filter and jumps to the top of the listing.
|
|
68
|
+
* Each time the filter is changed, the position jumps to the top of the listing.
|
|
63
69
|
* Use `i` to install apps, and `r` to remove apps. When you install or remove an app, `appman` drops out of `curses` mode, runs the `appman` command so you can see the result, and then prompts your to hit ENTER to return to `vappman.
|
|
70
|
+
* Use `t` to "test" an installed app. This launches a terminal emulator and then the app so you can see issues. This is not for daily use obviously, but for after install or when having unknown issues and you wish to start the investigation.
|
|
64
71
|
|
|
65
|
-
## Example Screenshot
|
|
72
|
+
## Example Screenshot (of v0.7 ... current release will vary slightly)
|
|
66
73
|
.
|
|
67
74
|
|
|
68
75
|
---
|
|
@@ -75,4 +82,8 @@ NOTES: in this example:
|
|
|
75
82
|
all the filtered apps; otherwise, the decoration suggests where you are in the
|
|
76
83
|
partial view of the filtered apps.
|
|
77
84
|
* the matching installed app has the '✔✔✔' prefix.
|
|
85
|
+
* the fixed top line shows some of the available action keys (e.g., `q` quits the app)
|
|
86
|
+
* use `?` to open the help screen describing all keys (including navigation)
|
|
78
87
|
|
|
88
|
+
## Screen Recording (Intro to vappman based on v0.7)
|
|
89
|
+
[](https://youtu.be/NUHYN9_DZtA)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
vappman/PowerWindow.py,sha256=pQGXsAMeuiHn-vtEiVG0rgW1eCslh3ukC-VrPhH_j3k,28587
|
|
2
|
+
vappman/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
vappman/main.py,sha256=FBTCzbOa9dCyzTHX3ietF9_avrMRareYFxmnd65wc2M,17066
|
|
4
|
+
vappman-0.8.dist-info/LICENSE,sha256=qB9OdnyyF6WYHiEIXVm0rOSdcf8e2ctorrtWs6CC5lU,1062
|
|
5
|
+
vappman-0.8.dist-info/METADATA,sha256=BJMibKDn0HtJFZcvP55MtNLnqK1P77NeTFOHkaDTm7o,4921
|
|
6
|
+
vappman-0.8.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
|
|
7
|
+
vappman-0.8.dist-info/entry_points.txt,sha256=7_1MiUvkCJoElLePOCJYqhkQN4xmadBRQCKupOwzt90,46
|
|
8
|
+
vappman-0.8.dist-info/top_level.txt,sha256=5_Gb5oZh7s2-i62gLXZ6INVALAV9D0-yqh0TvNqpPC4,8
|
|
9
|
+
vappman-0.8.dist-info/RECORD,,
|
vappman-0.6.dist-info/RECORD
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
vappman/PowerWindow.py,sha256=OLCX-RkbJZ2wwaY7M-4Eo9PQuR95TWrGNIY8DdVRpsE,28567
|
|
2
|
-
vappman/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
vappman/main.py,sha256=rSWpH_l_IgH3jR4HSG-H8lvmuuAZWStPo-AMtSIsZYY,10483
|
|
4
|
-
vappman-0.6.dist-info/LICENSE,sha256=qB9OdnyyF6WYHiEIXVm0rOSdcf8e2ctorrtWs6CC5lU,1062
|
|
5
|
-
vappman-0.6.dist-info/METADATA,sha256=pWiQZo-R_ePgEX3Yz9oAcNty2XBmYCArV--3ErQd_HI,3850
|
|
6
|
-
vappman-0.6.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
7
|
-
vappman-0.6.dist-info/entry_points.txt,sha256=7_1MiUvkCJoElLePOCJYqhkQN4xmadBRQCKupOwzt90,46
|
|
8
|
-
vappman-0.6.dist-info/top_level.txt,sha256=5_Gb5oZh7s2-i62gLXZ6INVALAV9D0-yqh0TvNqpPC4,8
|
|
9
|
-
vappman-0.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|