Skip to main content

hjkl_vim/
pending.rs

1/// Pending-state machine for second-key chords. The umbrella stores
2/// `Option<PendingState>`; when `Some`, it routes keys through `step`
3/// instead of the keymap trie.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum PendingState {
6    Replace { count: usize },
7    // 2b–2e variants land later.
8}
9
10/// One step of the reducer.
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub enum Outcome {
13    /// Need more keys — keep accumulating with new state.
14    Wait(PendingState),
15    /// Run this engine command, then clear pending.
16    Commit(crate::cmd::EngineCmd),
17    /// Cancel pending (Esc, invalid char, etc.). No engine call.
18    Cancel,
19    /// Pending state didn't consume this key — host should route it
20    /// normally (e.g. modifier-only key). Pending state stays alive.
21    Forward,
22}
23
24/// `Key` is intentionally minimal — hjkl-vim should not depend on
25/// crossterm. Hosts translate their native keys into this shape.
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum Key {
28    Char(char),
29    Esc,
30    Enter,
31    Backspace,
32    Tab,
33    // Add more variants only as later chunks require them.
34}
35
36pub fn step(state: PendingState, key: Key) -> Outcome {
37    match state {
38        PendingState::Replace { count } => match key {
39            Key::Esc => Outcome::Cancel,
40            Key::Char(ch) => Outcome::Commit(crate::cmd::EngineCmd::ReplaceChar { ch, count }),
41            Key::Enter => Outcome::Commit(crate::cmd::EngineCmd::ReplaceChar { ch: '\n', count }),
42            _ => Outcome::Cancel,
43        },
44    }
45}