From ff1760a4e9d668566e9936887e67cbddebda67b7 Mon Sep 17 00:00:00 2001 From: John Cavanaugh <59479+cavanaug@users.noreply.github.com> Date: Thu, 12 Feb 2026 15:52:26 -0800 Subject: [PATCH 1/4] feat: make help and priority key bindings configurable via taskrc Add taskrc parsing for 5 key bindings that had fields in KeyConfig but were never read from config: - uda.taskwarrior-tui.keyconfig.help (default: ?) - uda.taskwarrior-tui.keyconfig.priority-h (default: H) - uda.taskwarrior-tui.keyconfig.priority-m (default: M) - uda.taskwarrior-tui.keyconfig.priority-l (default: L) - uda.taskwarrior-tui.keyconfig.priority-n (default: N) Also adds priority keys to duplicate key validation in check(), adds unit tests for the new configurable keys, and updates docs/configuration/keys.md with the new options. --- docs/configuration/keys.md | 5 +++ src/keyconfig.rs | 73 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/docs/configuration/keys.md b/docs/configuration/keys.md index 1e942bda..df19dee1 100644 --- a/docs/configuration/keys.md +++ b/docs/configuration/keys.md @@ -30,4 +30,9 @@ uda.taskwarrior-tui.keyconfig.zoom=z uda.taskwarrior-tui.keyconfig.context-menu=c uda.taskwarrior-tui.keyconfig.next-tab=] uda.taskwarrior-tui.keyconfig.previous-tab=[ +uda.taskwarrior-tui.keyconfig.help=? +uda.taskwarrior-tui.keyconfig.priority-h=H +uda.taskwarrior-tui.keyconfig.priority-m=M +uda.taskwarrior-tui.keyconfig.priority-l=L +uda.taskwarrior-tui.keyconfig.priority-n=N ``` diff --git a/src/keyconfig.rs b/src/keyconfig.rs index c46073d5..ad67f6c2 100644 --- a/src/keyconfig.rs +++ b/src/keyconfig.rs @@ -146,6 +146,11 @@ impl KeyConfig { let shortcut7 = Self::get_config("uda.taskwarrior-tui.keyconfig.shortcut7", data); let shortcut8 = Self::get_config("uda.taskwarrior-tui.keyconfig.shortcut8", data); let shortcut9 = Self::get_config("uda.taskwarrior-tui.keyconfig.shortcut9", data); + let help = Self::get_config("uda.taskwarrior-tui.keyconfig.help", data); + let priority_h = Self::get_config("uda.taskwarrior-tui.keyconfig.priority-h", data); + let priority_m = Self::get_config("uda.taskwarrior-tui.keyconfig.priority-m", data); + let priority_l = Self::get_config("uda.taskwarrior-tui.keyconfig.priority-l", data); + let priority_n = Self::get_config("uda.taskwarrior-tui.keyconfig.priority-n", data); self.quit = quit.unwrap_or(self.quit); self.refresh = refresh.unwrap_or(self.refresh); @@ -184,6 +189,11 @@ impl KeyConfig { self.shortcut7 = shortcut7.unwrap_or(self.shortcut7); self.shortcut8 = shortcut8.unwrap_or(self.shortcut8); self.shortcut9 = shortcut9.unwrap_or(self.shortcut9); + self.help = help.unwrap_or(self.help); + self.priority_h = priority_h.unwrap_or(self.priority_h); + self.priority_m = priority_m.unwrap_or(self.priority_m); + self.priority_l = priority_l.unwrap_or(self.priority_l); + self.priority_n = priority_n.unwrap_or(self.priority_n); self.check() } @@ -218,6 +228,10 @@ impl KeyConfig { &self.context_menu, &self.next_tab, &self.previous_tab, + &self.priority_h, + &self.priority_m, + &self.priority_l, + &self.priority_n, ]; let l = elements.len(); elements.dedup(); @@ -258,4 +272,63 @@ fn has_just_one_char(s: &str) -> bool { #[cfg(test)] mod tests { use super::*; + + #[test] + fn test_defaults_when_config_absent() { + let data = ""; + let kc = KeyConfig::new(data).unwrap(); + assert_eq!(kc.help, KeyCode::Char('?')); + assert_eq!(kc.priority_h, KeyCode::Char('H')); + assert_eq!(kc.priority_m, KeyCode::Char('M')); + assert_eq!(kc.priority_l, KeyCode::Char('L')); + assert_eq!(kc.priority_n, KeyCode::Char('N')); + } + + #[test] + fn test_help_key_configurable() { + let data = "uda.taskwarrior-tui.keyconfig.help h\n"; + let kc = KeyConfig::new(data).unwrap(); + assert_eq!(kc.help, KeyCode::Char('h')); + } + + #[test] + fn test_priority_keys_configurable_hyphenated() { + let data = "uda.taskwarrior-tui.keyconfig.priority-h 1\n\ + uda.taskwarrior-tui.keyconfig.priority-m 2\n\ + uda.taskwarrior-tui.keyconfig.priority-l 3\n\ + uda.taskwarrior-tui.keyconfig.priority-n 4\n"; + let kc = KeyConfig::new(data).unwrap(); + assert_eq!(kc.priority_h, KeyCode::Char('1')); + assert_eq!(kc.priority_m, KeyCode::Char('2')); + assert_eq!(kc.priority_l, KeyCode::Char('3')); + assert_eq!(kc.priority_n, KeyCode::Char('4')); + } + + #[test] + fn test_priority_keys_configurable_underscored() { + // The fallback path replaces ALL hyphens in the config key with underscores, + // including those in "taskwarrior-tui". So the user must use fully underscored + // keys for the fallback to match (e.g. "taskwarrior_tui" not "taskwarrior-tui"). + let data = "uda.taskwarrior_tui.keyconfig.priority_h 1\n\ + uda.taskwarrior_tui.keyconfig.priority_m 2\n\ + uda.taskwarrior_tui.keyconfig.priority_l 3\n\ + uda.taskwarrior_tui.keyconfig.priority_n 4\n"; + let kc = KeyConfig::new(data).unwrap(); + assert_eq!(kc.priority_h, KeyCode::Char('1')); + assert_eq!(kc.priority_m, KeyCode::Char('2')); + assert_eq!(kc.priority_l, KeyCode::Char('3')); + assert_eq!(kc.priority_n, KeyCode::Char('4')); + } + + #[test] + fn test_existing_keys_still_work() { + let data = "uda.taskwarrior-tui.keyconfig.quit Q\n\ + uda.taskwarrior-tui.keyconfig.add n\n"; + let kc = KeyConfig::new(data).unwrap(); + assert_eq!(kc.quit, KeyCode::Char('Q')); + assert_eq!(kc.add, KeyCode::Char('n')); + // unset keys keep defaults + assert_eq!(kc.refresh, KeyCode::Char('r')); + assert_eq!(kc.down, KeyCode::Char('j')); + } } From 628cd6ad14fe00332380f9b30d9e16536846c8f4 Mon Sep 17 00:00:00 2001 From: John Cavanaugh <59479+cavanaug@users.noreply.github.com> Date: Sun, 15 Feb 2026 15:07:25 -0700 Subject: [PATCH 2/4] =?UTF-8?q?breaking:=20=F0=9F=92=A5=20Standardize=20pr?= =?UTF-8?q?iority=20key=20names=20to=20underscores?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docs(docs/configuration/keys.md): 📚 Update example config to priority_h/m/l/n to match code and avoid hyphen/underscore ambiguity test(src/keyconfig.rs): 🚨 Replace hyphen/underscore tests with a single underscored config test to reflect the new canonical keys --- docs/configuration/keys.md | 8 ++++---- src/keyconfig.rs | 34 +++++++++------------------------- 2 files changed, 13 insertions(+), 29 deletions(-) diff --git a/docs/configuration/keys.md b/docs/configuration/keys.md index df19dee1..9b9e74f4 100644 --- a/docs/configuration/keys.md +++ b/docs/configuration/keys.md @@ -31,8 +31,8 @@ uda.taskwarrior-tui.keyconfig.context-menu=c uda.taskwarrior-tui.keyconfig.next-tab=] uda.taskwarrior-tui.keyconfig.previous-tab=[ uda.taskwarrior-tui.keyconfig.help=? -uda.taskwarrior-tui.keyconfig.priority-h=H -uda.taskwarrior-tui.keyconfig.priority-m=M -uda.taskwarrior-tui.keyconfig.priority-l=L -uda.taskwarrior-tui.keyconfig.priority-n=N +uda.taskwarrior-tui.keyconfig.priority_h=H +uda.taskwarrior-tui.keyconfig.priority_m=M +uda.taskwarrior-tui.keyconfig.priority_l=L +uda.taskwarrior-tui.keyconfig.priority_n=N ``` diff --git a/src/keyconfig.rs b/src/keyconfig.rs index ad67f6c2..c77f07b4 100644 --- a/src/keyconfig.rs +++ b/src/keyconfig.rs @@ -147,10 +147,10 @@ impl KeyConfig { let shortcut8 = Self::get_config("uda.taskwarrior-tui.keyconfig.shortcut8", data); let shortcut9 = Self::get_config("uda.taskwarrior-tui.keyconfig.shortcut9", data); let help = Self::get_config("uda.taskwarrior-tui.keyconfig.help", data); - let priority_h = Self::get_config("uda.taskwarrior-tui.keyconfig.priority-h", data); - let priority_m = Self::get_config("uda.taskwarrior-tui.keyconfig.priority-m", data); - let priority_l = Self::get_config("uda.taskwarrior-tui.keyconfig.priority-l", data); - let priority_n = Self::get_config("uda.taskwarrior-tui.keyconfig.priority-n", data); + let priority_h = Self::get_config("uda.taskwarrior-tui.keyconfig.priority_h", data); + let priority_m = Self::get_config("uda.taskwarrior-tui.keyconfig.priority_m", data); + let priority_l = Self::get_config("uda.taskwarrior-tui.keyconfig.priority_l", data); + let priority_n = Self::get_config("uda.taskwarrior-tui.keyconfig.priority_n", data); self.quit = quit.unwrap_or(self.quit); self.refresh = refresh.unwrap_or(self.refresh); @@ -292,27 +292,11 @@ mod tests { } #[test] - fn test_priority_keys_configurable_hyphenated() { - let data = "uda.taskwarrior-tui.keyconfig.priority-h 1\n\ - uda.taskwarrior-tui.keyconfig.priority-m 2\n\ - uda.taskwarrior-tui.keyconfig.priority-l 3\n\ - uda.taskwarrior-tui.keyconfig.priority-n 4\n"; - let kc = KeyConfig::new(data).unwrap(); - assert_eq!(kc.priority_h, KeyCode::Char('1')); - assert_eq!(kc.priority_m, KeyCode::Char('2')); - assert_eq!(kc.priority_l, KeyCode::Char('3')); - assert_eq!(kc.priority_n, KeyCode::Char('4')); - } - - #[test] - fn test_priority_keys_configurable_underscored() { - // The fallback path replaces ALL hyphens in the config key with underscores, - // including those in "taskwarrior-tui". So the user must use fully underscored - // keys for the fallback to match (e.g. "taskwarrior_tui" not "taskwarrior-tui"). - let data = "uda.taskwarrior_tui.keyconfig.priority_h 1\n\ - uda.taskwarrior_tui.keyconfig.priority_m 2\n\ - uda.taskwarrior_tui.keyconfig.priority_l 3\n\ - uda.taskwarrior_tui.keyconfig.priority_n 4\n"; + fn test_priority_keys_configurable() { + let data = "uda.taskwarrior-tui.keyconfig.priority_h 1\n\ + uda.taskwarrior-tui.keyconfig.priority_m 2\n\ + uda.taskwarrior-tui.keyconfig.priority_l 3\n\ + uda.taskwarrior-tui.keyconfig.priority_n 4\n"; let kc = KeyConfig::new(data).unwrap(); assert_eq!(kc.priority_h, KeyCode::Char('1')); assert_eq!(kc.priority_m, KeyCode::Char('2')); From 5f1192e30219d95c96b74c70d572b33cd06d9146 Mon Sep 17 00:00:00 2001 From: John Cavanaugh <59479+cavanaug@users.noreply.github.com> Date: Sun, 15 Feb 2026 22:56:10 -0700 Subject: [PATCH 3/4] feat: standardize priority config keys to hyphens and add priority keybinds to help screen Change config key names from priority_h/m/l/n to priority-h/m/l/n for consistency with all other multi-word config keys (go-to-bottom, start-stop, context-menu, etc.). Backward compatible via get_config() fallback that matches underscore variants. Also add priority H/M/L/N keybindings to the help screen template. --- docs/configuration/keys.md | 8 ++++---- src/help.rs | 4 ++++ src/help.tmpl | 8 ++++++++ src/keyconfig.rs | 16 ++++++++-------- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/docs/configuration/keys.md b/docs/configuration/keys.md index 9b9e74f4..df19dee1 100644 --- a/docs/configuration/keys.md +++ b/docs/configuration/keys.md @@ -31,8 +31,8 @@ uda.taskwarrior-tui.keyconfig.context-menu=c uda.taskwarrior-tui.keyconfig.next-tab=] uda.taskwarrior-tui.keyconfig.previous-tab=[ uda.taskwarrior-tui.keyconfig.help=? -uda.taskwarrior-tui.keyconfig.priority_h=H -uda.taskwarrior-tui.keyconfig.priority_m=M -uda.taskwarrior-tui.keyconfig.priority_l=L -uda.taskwarrior-tui.keyconfig.priority_n=N +uda.taskwarrior-tui.keyconfig.priority-h=H +uda.taskwarrior-tui.keyconfig.priority-m=M +uda.taskwarrior-tui.keyconfig.priority-l=L +uda.taskwarrior-tui.keyconfig.priority-n=N ``` diff --git a/src/help.rs b/src/help.rs index 653fc9dc..eee10b8b 100644 --- a/src/help.rs +++ b/src/help.rs @@ -59,6 +59,10 @@ fn keycode_for(name: &str, kc: &KeyConfig) -> KeyCode { "shortcut8" => kc.shortcut8, "context_menu" => kc.context_menu, "help" => kc.help, + "priority_h" => kc.priority_h, + "priority_m" => kc.priority_m, + "priority_l" => kc.priority_l, + "priority_n" => kc.priority_n, _ => KeyCode::Null, } } diff --git a/src/help.tmpl b/src/help.tmpl index e8575220..2dd4619d 100644 --- a/src/help.tmpl +++ b/src/help.tmpl @@ -54,6 +54,14 @@ Keybindings for task report: {{annotate}}: task {selected} annotate {string} - Annotate current task + {{priority_h}}: priority H - Set priority to High + + {{priority_m}}: priority M - Set priority to Medium + + {{priority_l}}: priority L - Set priority to Low + + {{priority_n}}: priority N - Remove priority + Ctrl-e: scroll down task details - Scroll task details view down one line Ctrl-y: scroll up task details - Scroll task details view up one line diff --git a/src/keyconfig.rs b/src/keyconfig.rs index c77f07b4..8471408c 100644 --- a/src/keyconfig.rs +++ b/src/keyconfig.rs @@ -147,10 +147,10 @@ impl KeyConfig { let shortcut8 = Self::get_config("uda.taskwarrior-tui.keyconfig.shortcut8", data); let shortcut9 = Self::get_config("uda.taskwarrior-tui.keyconfig.shortcut9", data); let help = Self::get_config("uda.taskwarrior-tui.keyconfig.help", data); - let priority_h = Self::get_config("uda.taskwarrior-tui.keyconfig.priority_h", data); - let priority_m = Self::get_config("uda.taskwarrior-tui.keyconfig.priority_m", data); - let priority_l = Self::get_config("uda.taskwarrior-tui.keyconfig.priority_l", data); - let priority_n = Self::get_config("uda.taskwarrior-tui.keyconfig.priority_n", data); + let priority_h = Self::get_config("uda.taskwarrior-tui.keyconfig.priority-h", data); + let priority_m = Self::get_config("uda.taskwarrior-tui.keyconfig.priority-m", data); + let priority_l = Self::get_config("uda.taskwarrior-tui.keyconfig.priority-l", data); + let priority_n = Self::get_config("uda.taskwarrior-tui.keyconfig.priority-n", data); self.quit = quit.unwrap_or(self.quit); self.refresh = refresh.unwrap_or(self.refresh); @@ -293,10 +293,10 @@ mod tests { #[test] fn test_priority_keys_configurable() { - let data = "uda.taskwarrior-tui.keyconfig.priority_h 1\n\ - uda.taskwarrior-tui.keyconfig.priority_m 2\n\ - uda.taskwarrior-tui.keyconfig.priority_l 3\n\ - uda.taskwarrior-tui.keyconfig.priority_n 4\n"; + let data = "uda.taskwarrior-tui.keyconfig.priority-h 1\n\ + uda.taskwarrior-tui.keyconfig.priority-m 2\n\ + uda.taskwarrior-tui.keyconfig.priority-l 3\n\ + uda.taskwarrior-tui.keyconfig.priority-n 4\n"; let kc = KeyConfig::new(data).unwrap(); assert_eq!(kc.priority_h, KeyCode::Char('1')); assert_eq!(kc.priority_m, KeyCode::Char('2')); From 85e545ed0f33218b27648b8e1de08bc41cf8ed8d Mon Sep 17 00:00:00 2001 From: John Cavanaugh <59479+cavanaug@users.noreply.github.com> Date: Wed, 18 Feb 2026 16:31:17 -0800 Subject: [PATCH 4/4] fix: update help popup test scroll percentage after priority key additions --- src/app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.rs b/src/app.rs index 4187afa6..54ddd6f3 100644 --- a/src/app.rs +++ b/src/app.rs @@ -4747,7 +4747,7 @@ mod tests { "│ │", "│ [: Previous view │", "╰──────────────────────────────────────╯", - " 8% ───────────────────────────────────", + " 7% ───────────────────────────────────", ]); for i in 1..=4 {