From 39a9f95432e4ee5ef1d884ea9b36c11cf17ffe65 Mon Sep 17 00:00:00 2001 From: Ayo Date: Sat, 11 Jul 2026 13:31:39 +0200 Subject: [PATCH] feat(tasks): hotkeys --- tasks | 69 +++++++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/tasks b/tasks index ee2b8bf..b9d7023 100755 --- a/tasks +++ b/tasks @@ -391,10 +391,10 @@ HELP_TEXT = [ " Tab cycle status filter (all → each folder)", " s cycle sort (status+priority / priority / updated)", " Enter view full task", - " n new task", - " e edit in $EDITOR (re-dates filename, logs 'edited')", - " m move to another status folder", - " p cycle priority c set context", + " c create (opens $EDITOR pre-filled from the template)", + " o open in $EDITOR (re-dates filename, logs 'edited')", + " move: e / b → backlog n → next i → in-progress d → done", + " p cycle priority @ set context", " l add a log entry", " r reload from disk", " ? this help q quit", @@ -411,7 +411,7 @@ class TUI: self.tasks = [] self.sel = 0 self.top = 0 - self.filter_status = None + self.filter_status = "in-progress" # what you're actively working on, first self.sort_mode = 0 self.msg = "" self.reload() @@ -468,7 +468,7 @@ class TUI: self.scr.addnstr(div, 0, "─" * (w - 1), w - 1) self._draw_preview(div + 1, h - 2, w) - footer = self.msg or " n:new e:edit m:move p:prio c:ctx l:log Enter:view ?:help q:quit " + footer = self.msg or " c:create o:open b/e:backlog n:next i:in-prog d:done p:prio @:ctx l:log Enter:view ?:help q:quit " self.scr.addnstr(h - 1, 0, footer.ljust(w - 1), w - 1, curses.A_REVERSE) self.scr.refresh() @@ -523,45 +523,42 @@ class TUI: self.msg = " " + msg + " " # --- actions --------------------------------------------------------- - def act_new(self): + def _run_editor(self, path): + editor = os.environ.get("EDITOR") or shutil.which("nano") or shutil.which("vi") or "vi" + curses.endwin() + subprocess.call([editor, path]) + self.scr = curses.initscr() + curses.curs_set(0) + + def act_create(self): title = self.prompt("New task title:") if not title: self.flash("cancelled") return - pri = self.choose("Priority", PRIORITIES) or "P2" - ctx = self.choose("Context", CONTEXTS) or "@admin" - status = self.choose("Status", STATUSES) or "backlog" - goal = self.prompt("Goal (optional):") - nxt = self.prompt("Next action (optional):") - t = create_task(title, priority=pri, context=ctx, - status=status, goal=goal, next_action=nxt) + t = create_task(title) # template-filled draft in backlog/ + self._run_editor(t.path) # flesh it out in $EDITOR self.reload() self.flash(f"created {t.filename}") - def act_edit(self): + def act_open(self): t = self.current() if not t: return - editor = os.environ.get("EDITOR") or shutil.which("nano") or shutil.which("vi") or "vi" - curses.endwin() - subprocess.call([editor, t.path]) - Task(t.path).append_log("edited.") - self.scr = curses.initscr() - curses.curs_set(0) + self._run_editor(t.path) + Task(t.path).append_log("edited.") # re-dates filename, logs 'edited' self.reload() self.flash("saved & re-dated") - def act_move(self): + def act_move_to(self, status): t = self.current() if not t: return - dest = self.choose("Move to", STATUSES) - if not dest: - self.flash("cancelled") + if t.status == status: + self.flash(f"already in {status}") return - t.move_to(dest) + t.move_to(status) self.reload() - self.flash(f"moved -> {dest}") + self.flash(f"moved -> {status}") def act_field(self, key, options=None): t = self.current() @@ -643,15 +640,21 @@ class TUI: self._sort() elif ch in (curses.KEY_ENTER, 10, 13): self.view_full() + elif ch == ord("c"): + self.act_create() + elif ch == ord("o"): + self.act_open() + elif ch in (ord("e"), ord("b")): + self.act_move_to("backlog") elif ch == ord("n"): - self.act_new() - elif ch == ord("e"): - self.act_edit() - elif ch == ord("m"): - self.act_move() + self.act_move_to("next") + elif ch == ord("i"): + self.act_move_to("in-progress") + elif ch == ord("d"): + self.act_move_to("done") elif ch == ord("p"): self.act_cycle_priority() - elif ch == ord("c"): + elif ch == ord("@"): self.act_field("context", CONTEXTS) elif ch == ord("l"): self.act_log()