Added a toggle so that work can be paused
This commit is contained in:
parent
0239c19e7e
commit
d7cedba890
3 changed files with 74 additions and 39 deletions
4
TODO
4
TODO
|
|
@ -8,10 +8,11 @@ Todo
|
|||
- Need to use conventional version numbers for pypi. See pep0440.
|
||||
- Add ESC as an alternative to 'q' for quit. If looking at Help, ESC should just
|
||||
exit the help screen.
|
||||
- Add means to pause and unpause all current jobs.
|
||||
- Have a sandbox for unsafe (or all) tools.
|
||||
- Statuses' pretty names and variable names don't match.
|
||||
- Report on python doctests. (also coverage of)
|
||||
- Treat any compressed file as though it is uncompressed. But the metadata tool
|
||||
should still report on the original compressed file.
|
||||
|
||||
|
||||
Done
|
||||
|
|
@ -146,6 +147,7 @@ Done
|
|||
- Ignore other input while help screen is showing.
|
||||
- Have an option to turn off all automatic work.
|
||||
<- The 'working' switch does this
|
||||
- Add means to pause and unpause all current jobs.
|
||||
|
||||
A-syntax, B-tests, C-auto docs, D-lint, E-coverage, F-profile, G-tidy, H-import deps
|
||||
A B C D E F G H
|
||||
|
|
|
|||
|
|
@ -26,15 +26,15 @@
|
|||
│ [0m[38;2;0;255;0m[48;2;0;0;0mn[0m[38;2;255;255;255m[48;2;0;0;0m - Move to the next issue. [0m[38;2;255;255;255m[48;2;100;100;100m [0m[38;2;255;255;255m[48;2;0;0;0m│
|
||||
│ [0m[38;2;0;255;0m[48;2;0;0;0mN[0m[38;2;255;255;255m[48;2;0;0;0m - Move to the next issue of the c[0m[38;2;255;255;255m[48;2;100;100;100m [0m[38;2;255;255;255m[48;2;0;0;0m│
|
||||
│ [0m[38;2;0;255;0m[48;2;0;0;0mo[0m[38;2;255;255;255m[48;2;0;0;0m - Order files by type, or by dire[0m[38;2;255;255;255m[48;2;100;100;100m [0m[38;2;255;255;255m[48;2;0;0;0m│
|
||||
│ [0m[38;2;0;255;0m[48;2;0;0;0mp[0m[38;2;255;255;255m[48;2;0;0;0m - Pause work. (toggle) [0m[38;2;255;255;255m[48;2;100;100;100m [0m[38;2;255;255;255m[48;2;0;0;0m│
|
||||
│ [0m[38;2;0;255;0m[48;2;0;0;0mw[0m[38;2;255;255;255m[48;2;0;0;0m - Watch the filesystem for change[0m[38;2;255;255;255m[48;2;100;100;100m [0m[38;2;255;255;255m[48;2;0;0;0m│
|
||||
│ [0m[38;2;0;255;0m[48;2;0;0;0ms[0m[38;2;255;255;255m[48;2;0;0;0m - Change the appearance of result[0m[38;2;255;255;255m[48;2;100;100;100m [0m[38;2;255;255;255m[48;2;0;0;0m│
|
||||
│ [0m[38;2;0;255;0m[48;2;0;0;0mq[0m[38;2;255;255;255m[48;2;0;0;0m - Quit. [0m[38;2;255;255;255m[48;2;100;100;100m [0m[38;2;255;255;255m[48;2;0;0;0m│
|
||||
│ [0m[38;2;255;255;255m[48;2;100;100;100m [0m[38;2;255;255;255m[48;2;0;0;0m│
|
||||
│Statuses: [0m[38;2;255;255;255m[48;2;100;100;100m [0m[38;2;255;255;255m[48;2;0;0;0m│
|
||||
│ Normal [0m[38;2;255;255;255m[48;2;100;100;100m [0m[38;2;255;255;255m[48;2;0;0;0m│
|
||||
│ [0m[38;2;0;255;0m[48;2;0;0;0m [0m[38;2;255;255;255m[48;2;0;0;0m No problems [0m[38;2;255;255;255m[48;2;100;100;100m [0m[38;2;255;255;255m[48;2;0;0;0m│
|
||||
│ [0m[38;2;255;0;0m[48;2;0;0;0m [0m[38;2;255;255;255m[48;2;0;0;0m Problems [0m[38;2;255;255;255m[48;2;100;100;100m [0m[38;2;255;255;255m[48;2;0;0;0m│
|
||||
│ [0m[38;2;0;255;0m[48;2;0;0;0m [0m[38;2;255;255;255m[48;2;0;0;0m No problems │
|
||||
│ [0m[38;2;255;0;0m[48;2;0;0;0m [0m[38;2;255;255;255m[48;2;0;0;0m Problems │
|
||||
│ [0m[38;2;100;100;100m[48;2;0;0;0m [0m[38;2;255;255;255m[48;2;0;0;0m Not applicable │
|
||||
│ [0m[38;2;255;255;0m[48;2;0;0;0m [0m[38;2;255;255;255m[48;2;0;0;0m Running │
|
||||
│[0m[38;2;255;255;255m[48;2;100;100;100m [0m[38;2;255;255;255m[48;2;0;0;0m │
|
||||
└──────────────────────────────────────┘[0m
|
||||
103
vigil
103
vigil
|
|
@ -32,6 +32,7 @@ Keys:
|
|||
*n - Move to the next issue.
|
||||
*N - Move to the next issue of the current tool.
|
||||
*o - Order files by type, or by directory location. (toggle)
|
||||
*p - Pause work. (toggle)
|
||||
*w - Watch the filesystem for changes. (toggle)
|
||||
*s - Change the appearance of result statuses. (toggle)
|
||||
*q - Quit.
|
||||
|
|
@ -588,6 +589,7 @@ class Screen:
|
|||
self._is_log_visible = True
|
||||
self._is_help_visible = False
|
||||
self._is_watching_filesystem = False
|
||||
self._is_paused = False
|
||||
self.toggle_watch_filesystem()
|
||||
self._make_widgets()
|
||||
self._make_keymap()
|
||||
|
|
@ -722,6 +724,17 @@ class Screen:
|
|||
self._main_loop.remove_reader(self._watch_manager.get_fd())
|
||||
self._watch_manager = None
|
||||
|
||||
def toggle_pause(self):
|
||||
self._is_paused = not self._is_paused
|
||||
self._log.log_command("Paused work." if self._is_paused else
|
||||
"Continuing work.")
|
||||
if self._is_paused:
|
||||
for runner in self.runners:
|
||||
runner.pause()
|
||||
else:
|
||||
for runner in self.runners:
|
||||
runner.continue_()
|
||||
|
||||
def quit_(self):
|
||||
raise KeyboardInterrupt
|
||||
|
||||
|
|
@ -777,16 +790,19 @@ class Screen:
|
|||
action(self)
|
||||
self._appearance_changed_event.set()
|
||||
|
||||
_STATUS_BAR = _highlight_chars(" *help *quit *d,*c,*j,*k:navigate *turn"
|
||||
" *log *edit *next *watch *order *statuses",
|
||||
Log.GREEN_STYLE)
|
||||
_STATUS_BAR = _highlight_chars(
|
||||
" *help *quit *d,*c,*j,*k:navigate *turn *log *edit *next *pause"
|
||||
" *watch *order *statuses", Log.GREEN_STYLE)
|
||||
|
||||
@functools.lru_cache(maxsize=2)
|
||||
def _get_status_bar_appearance(self, width, is_directory_sort,
|
||||
is_watching_filesystem, progress_bar_size):
|
||||
is_watching_filesystem, is_paused,
|
||||
progress_bar_size):
|
||||
ordering_text = "directory" if is_directory_sort else "type "
|
||||
watching_text = "watching" if is_watching_filesystem else "--------"
|
||||
indicators = " %s order:%s " % (watching_text, ordering_text)
|
||||
paused_text = "paused" if is_paused else "------"
|
||||
indicators = " %s %s order:%s " % (paused_text, watching_text,
|
||||
ordering_text)
|
||||
spacing = " " * (width - len(self._STATUS_BAR) - len(indicators))
|
||||
bar = (self._STATUS_BAR[:width - len(indicators)] + spacing +
|
||||
indicators)[:width]
|
||||
|
|
@ -809,7 +825,7 @@ class Screen:
|
|||
self._summary.result_total)
|
||||
status_bar_appearance = self._get_status_bar_appearance(
|
||||
width, self._summary.is_directory_sort,
|
||||
self._is_watching_filesystem, progress_bar_size)
|
||||
self._is_watching_filesystem, self._is_paused, progress_bar_size)
|
||||
return (self._layouts[self._is_log_visible][self._is_listing_portrait]
|
||||
.appearance((width, height-len(status_bar_appearance))) +
|
||||
status_bar_appearance)
|
||||
|
|
@ -823,7 +839,8 @@ class Screen:
|
|||
({"K", "end"}, listing_right), ({"o"}, toggle_sort),
|
||||
({"n"}, move_to_next_issue), ({"N"}, move_to_next_issue_of_tool),
|
||||
({"e"}, edit_file), ({"s"}, toggle_status_style),
|
||||
({"w"}, toggle_watch_filesystem), ({"q"}, quit_)]
|
||||
({"w"}, toggle_watch_filesystem), ({"q"}, quit_),
|
||||
({"p"}, toggle_pause)]
|
||||
|
||||
|
||||
def get_cpu_temperature():
|
||||
|
|
@ -872,6 +889,12 @@ class Worker:
|
|||
self.child_connection.send([tool, path])
|
||||
return self.child_connection.recv()
|
||||
|
||||
def pause(self):
|
||||
os.kill(self.process.pid, signal.SIGSTOP)
|
||||
|
||||
def continue_(self):
|
||||
os.kill(self.process.pid, signal.SIGCONT)
|
||||
|
||||
def stop(self):
|
||||
os.kill(self.process.pid, signal.SIGKILL)
|
||||
|
||||
|
|
@ -901,6 +924,12 @@ class Runner:
|
|||
pass
|
||||
jobs_added_event.clear()
|
||||
|
||||
def pause(self):
|
||||
self.worker.pause()
|
||||
|
||||
def continue_(self):
|
||||
self.worker.continue_()
|
||||
|
||||
|
||||
_UPDATE_THREAD_STOPPED = False
|
||||
|
||||
|
|
@ -914,7 +943,7 @@ def update_screen(main_widget, appearance_changed_event):
|
|||
fill3.patch_screen(main_widget)
|
||||
|
||||
|
||||
def main(root_path, urwid_screen):
|
||||
def main(root_path):
|
||||
global _UPDATE_THREAD_STOPPED
|
||||
os.chdir(root_path) # FIX: Don't change directory if possible.
|
||||
loop = asyncio.get_event_loop()
|
||||
|
|
@ -942,40 +971,46 @@ def main(root_path, urwid_screen):
|
|||
summary.sync_with_filesystem()
|
||||
log.log_message("Program started.")
|
||||
jobs_added_event.set()
|
||||
update_display_thread = threading.Thread(
|
||||
target=update_screen, args=(screen, appearance_changed_event),
|
||||
daemon=True)
|
||||
update_display_thread.start()
|
||||
loop.add_reader(sys.stdin, screen.on_keypressed, urwid_screen)
|
||||
runners = [Runner() for index in range(multiprocessing.cpu_count() * 2)]
|
||||
screen.runners = runners
|
||||
for runner in runners:
|
||||
args = (summary, log, jobs_added_event, appearance_changed_event)
|
||||
threading.Thread(target=runner.job_runner, args=args,
|
||||
daemon=True).start()
|
||||
if screen._is_paused:
|
||||
for runner in runners:
|
||||
runner.pause()
|
||||
|
||||
def on_window_resize(n, frame):
|
||||
appearance_changed_event.set()
|
||||
signal.signal(signal.SIGWINCH, on_window_resize)
|
||||
appearance_changed_event.set()
|
||||
try:
|
||||
loop.run_forever()
|
||||
except KeyboardInterrupt:
|
||||
log.log_message("Program stopped.")
|
||||
_UPDATE_THREAD_STOPPED = True
|
||||
appearance_changed_event.set()
|
||||
update_display_thread.join()
|
||||
for runner in runners:
|
||||
runner.worker.stop()
|
||||
runner.is_running = False
|
||||
for runner in runners:
|
||||
runner.result.reset()
|
||||
# Cannot pickle generators, locks, sockets or events.
|
||||
(summary.closest_placeholder_generator, summary._lock,
|
||||
summary._jobs_added_event, screen._appearance_changed_event,
|
||||
screen._main_loop, screen._watch_manager,
|
||||
log._appearance_changed_event) = [None] * 7
|
||||
open_compressed = functools.partial(gzip.open, compresslevel=1)
|
||||
dump_pickle_safe(screen, pickle_path, open=open_compressed)
|
||||
update_display_thread = threading.Thread(
|
||||
target=update_screen, args=(screen, appearance_changed_event),
|
||||
daemon=True)
|
||||
with terminal.hidden_cursor():
|
||||
with terminal.urwid_screen() as urwid_screen:
|
||||
update_display_thread.start()
|
||||
loop.add_reader(sys.stdin, screen.on_keypressed, urwid_screen)
|
||||
try:
|
||||
loop.run_forever()
|
||||
except KeyboardInterrupt:
|
||||
log.log_message("Program stopped.")
|
||||
_UPDATE_THREAD_STOPPED = True
|
||||
appearance_changed_event.set()
|
||||
update_display_thread.join()
|
||||
for runner in runners:
|
||||
runner.worker.stop()
|
||||
runner.is_running = False
|
||||
for runner in runners:
|
||||
runner.result.reset()
|
||||
# Cannot pickle generators, locks, sockets or events.
|
||||
(summary.closest_placeholder_generator, summary._lock,
|
||||
summary._jobs_added_event, screen._appearance_changed_event,
|
||||
screen._main_loop, screen._watch_manager, screen.runners,
|
||||
log._appearance_changed_event) = [None] * 8
|
||||
open_compressed = functools.partial(gzip.open, compresslevel=1)
|
||||
dump_pickle_safe(screen, pickle_path, open=open_compressed)
|
||||
|
||||
|
||||
def manage_cache(root_path):
|
||||
|
|
@ -996,9 +1031,7 @@ if __name__ == "__main__":
|
|||
root_path = os.path.abspath(sys.argv[1])
|
||||
with terminal.console_title("vigil: " + os.path.basename(root_path)):
|
||||
manage_cache(root_path)
|
||||
with terminal.hidden_cursor():
|
||||
with terminal.urwid_screen() as urwid_screen:
|
||||
main(root_path, urwid_screen)
|
||||
main(root_path)
|
||||
else:
|
||||
usage = __doc__.replace("*", "")
|
||||
print(usage)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue