Define the Mutt-like TUI keymap

This commit is contained in:
Hermes Agent
2026-08-10 08:03:20 +00:00
parent c82c792699
commit 639ae0d08e
4 changed files with 519 additions and 80 deletions

View File

@@ -13,7 +13,7 @@ use ironstorage::{
};
use crate::{
action::Action,
action::{Action, WorkflowAction},
editor::EntryEditor,
sidebar::{Sidebar, SidebarIntent},
viewer::EntryViewer,
@@ -137,6 +137,7 @@ pub enum AppEffect {
entry: String,
editor: Box<EntryEditor>,
},
OpenWorkflow(WorkflowAction),
ManualLock,
}
@@ -200,6 +201,14 @@ impl App {
self.mode
}
pub fn help_context_mode(&self) -> Mode {
if self.mode == Mode::Help {
self.suspended_mode.unwrap_or(Mode::Browser)
} else {
self.mode
}
}
pub fn focus(&self) -> PaneFocus {
self.focus
}
@@ -434,7 +443,7 @@ impl App {
return AppEffect::None;
}
match action {
Action::Quit if matches!(self.mode, Mode::Browser | Mode::Viewer) => {
Action::Quit if matches!(self.mode, Mode::Browser | Mode::Viewer | Mode::Locked) => {
self.should_quit = true;
}
Action::Help => {
@@ -618,6 +627,19 @@ impl App {
}
Action::ConfirmDiscard => self.discard_editor(),
Action::KeepEditing => self.keep_editing(),
Action::Initialize
| Action::InsertEntry
| Action::GenerateEntry
| Action::Grep
| Action::RemoveEntry
| Action::MoveEntry
| Action::CopyEntry
| Action::GitPull
| Action::GitPush => {
let workflow = action.workflow().expect("matched workflow action");
self.status = format!("Selected {} workflow", workflow_label(workflow));
return AppEffect::OpenWorkflow(workflow);
}
Action::Quit => {}
}
AppEffect::None
@@ -931,6 +953,20 @@ impl App {
}
}
fn workflow_label(workflow: WorkflowAction) -> &'static str {
match workflow {
WorkflowAction::Initialize => "initialization",
WorkflowAction::InsertEntry => "entry insertion",
WorkflowAction::GenerateEntry => "entry generation",
WorkflowAction::Grep => "decrypted grep",
WorkflowAction::RemoveEntry => "entry removal",
WorkflowAction::MoveEntry => "entry move",
WorkflowAction::CopyEntry => "entry copy",
WorkflowAction::GitPull => "Git pull",
WorkflowAction::GitPush => "Git push",
}
}
#[cfg(test)]
mod tests {
use super::*;
@@ -1135,4 +1171,20 @@ mod tests {
b"generated-under-help"
);
}
#[test]
fn direct_workflow_keys_dispatch_typed_ui_effects_without_domain_work() {
let mut app = App::new();
assert!(matches!(
app.dispatch(Action::InsertEntry),
AppEffect::OpenWorkflow(WorkflowAction::InsertEntry)
));
assert!(app.status().contains("entry insertion"));
app.open_test_document("email/personal", fixture_document("email/personal"));
assert!(matches!(
app.dispatch(Action::RemoveEntry),
AppEffect::OpenWorkflow(WorkflowAction::RemoveEntry)
));
assert!(app.status().contains("entry removal"));
}
}