From f859c40eb164d79cbc8bfba0d7d208f873485071 Mon Sep 17 00:00:00 2001 From: Alexander Date: Sun, 10 May 2026 10:59:43 +0200 Subject: [PATCH] feat: add AppAction enum and Doom Emacs keybinding configuration 18-variant AppAction enum + build_normal_keymap() with hjkl, gg/G, gt/gT, 1-6 tabs, C-d/C-u, SPC leader tree (buffer/help/quit/notifications). Ultraworked with [Sisyphus](https://github.com/code-yeongyu/claude-agent) Co-authored-by: Sisyphus --- src/input/action.rs | 25 +++++++++++++++++++ src/input/keymap.rs | 61 +++++++++++++++++++++++++++++++++++++++++++++ src/input/mod.rs | 5 ++++ 3 files changed, 91 insertions(+) create mode 100644 src/input/action.rs create mode 100644 src/input/keymap.rs create mode 100644 src/input/mod.rs diff --git a/src/input/action.rs b/src/input/action.rs new file mode 100644 index 0000000..2cbb265 --- /dev/null +++ b/src/input/action.rs @@ -0,0 +1,25 @@ +#[derive(Clone, Debug)] +pub enum AppAction { + // Movement + MoveUp, + MoveDown, + FocusLeft, + FocusRight, + CycleFocus, + GotoFirst, + GotoLast, + HalfPageDown, + HalfPageUp, + + // Tabs + NextTab, + PrevTab, + GotoTab(usize), + + // System + Quit, + Refresh, + ShowHelp, + ToggleNotifications, + Escape, +} diff --git a/src/input/keymap.rs b/src/input/keymap.rs new file mode 100644 index 0000000..90e4a65 --- /dev/null +++ b/src/input/keymap.rs @@ -0,0 +1,61 @@ +use evil_keys::KeyTrie; + +use crate::input::action::AppAction; + +pub fn build_normal_keymap() -> KeyTrie { + let mut t = KeyTrie::new("normal"); + + t.bind_desc("j", AppAction::MoveDown, "down").unwrap(); + t.bind_desc("k", AppAction::MoveUp, "up").unwrap(); + t.bind_desc("h", AppAction::FocusLeft, "focus left") + .unwrap(); + t.bind_desc("l", AppAction::FocusRight, "focus right") + .unwrap(); + t.bind_desc("Tab", AppAction::CycleFocus, "cycle focus") + .unwrap(); + t.bind_desc("G", AppAction::GotoLast, "last item").unwrap(); + t.bind_desc("C-d", AppAction::HalfPageDown, "half page down") + .unwrap(); + t.bind_desc("C-u", AppAction::HalfPageUp, "half page up") + .unwrap(); + + t.group("g", "+goto", |g| { + g.bind_desc("g", AppAction::GotoFirst, "first item")?; + g.bind_desc("t", AppAction::NextTab, "next tab")?; + g.bind_desc("T", AppAction::PrevTab, "prev tab")?; + Ok(()) + }) + .unwrap(); + + for i in 1..=6 { + t.bind(&format!("{i}"), AppAction::GotoTab(i - 1)).unwrap(); + } + + t.group("SPC", "+leader", |g| { + g.group("b", "+buffer", |b| { + b.bind_desc("l", AppAction::GotoTab(0), "library")?; + b.bind_desc("w", AppAction::GotoTab(1), "wanted")?; + b.bind_desc("q", AppAction::GotoTab(2), "queue")?; + b.bind_desc("h", AppAction::GotoTab(3), "history")?; + b.bind_desc("n", AppAction::NextTab, "next")?; + b.bind_desc("p", AppAction::PrevTab, "prev")?; + Ok(()) + })?; + g.bind_desc("h", AppAction::ShowHelp, "help")?; + g.bind_desc("q", AppAction::Quit, "quit")?; + g.bind_desc("n", AppAction::ToggleNotifications, "notifications")?; + Ok(()) + }) + .unwrap(); + + t.bind("Esc", AppAction::Escape).unwrap(); + t.bind("?", AppAction::ShowHelp).unwrap(); + + t +} + +pub fn build_insert_keymap() -> KeyTrie { + let mut t = KeyTrie::new("insert"); + t.bind("Esc", AppAction::Escape).unwrap(); + t +} diff --git a/src/input/mod.rs b/src/input/mod.rs new file mode 100644 index 0000000..14d72d8 --- /dev/null +++ b/src/input/mod.rs @@ -0,0 +1,5 @@ +pub mod action; +pub mod keymap; + +pub use action::AppAction; +pub use keymap::{build_insert_keymap, build_normal_keymap};