Skip to main content

escriba_core/
action.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4use crate::edit::Edit;
5use crate::mode::Mode;
6use crate::motion::{Motion, Operator};
7
8/// A fully-resolved editor action — what the keymap emits, what the buffer
9/// consumes.
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
11pub enum Action {
12    /// Move every cursor by `motion`.
13    Move(Motion),
14    /// Begin an operator (the `d`/`c`/`y` key). The editor enters
15    /// operator-pending: the next motion composes into an [`Action::ApplyOperator`].
16    /// Resolved by the operator-pending FSM, never executed directly.
17    Operator(Operator),
18    /// Apply a pending operator over a motion (delete-word, yank-line, etc.).
19    ApplyOperator {
20        op: Operator,
21        motion: Motion,
22    },
23    /// Apply a primitive edit at each cursor.
24    Edit(Edit),
25    /// Enter the given mode.
26    ChangeMode(Mode),
27    /// Run a named command (via the command registry).
28    Command {
29        name: String,
30        args: Vec<String>,
31    },
32    /// Insert a character at each caret. Separate from Edit so the keymap
33    /// can stay ignorant of rope details.
34    InsertChar(char),
35    /// Submit a minibuffer / command-mode line (e.g. `:w`, `:q`).
36    SubmitCommand,
37    /// Undo / redo one change.
38    Undo,
39    Redo,
40    /// Save the current buffer.
41    Save,
42    /// Quit the editor.
43    Quit,
44    /// No-op — used when a key sequence is pending but not yet complete.
45    Pending,
46}
47
48/// An [`Action`] with an optional repetition count (vim's `5dd`, `10k`).
49#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
50pub struct CountedAction {
51    pub count: u32,
52    pub action: Action,
53}
54
55impl CountedAction {
56    #[must_use]
57    pub fn once(action: Action) -> Self {
58        Self { count: 1, action }
59    }
60
61    #[must_use]
62    pub fn repeated(count: u32, action: Action) -> Self {
63        Self {
64            count: count.max(1),
65            action,
66        }
67    }
68}