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 /// Apply a pending operator over a motion (delete-word, yank-line, etc.).
15 ApplyOperator {
16 op: Operator,
17 motion: Motion,
18 },
19 /// Apply a primitive edit at each cursor.
20 Edit(Edit),
21 /// Enter the given mode.
22 ChangeMode(Mode),
23 /// Run a named command (via the command registry).
24 Command {
25 name: String,
26 args: Vec<String>,
27 },
28 /// Insert a character at each caret. Separate from Edit so the keymap
29 /// can stay ignorant of rope details.
30 InsertChar(char),
31 /// Submit a minibuffer / command-mode line (e.g. `:w`, `:q`).
32 SubmitCommand,
33 /// Undo / redo one change.
34 Undo,
35 Redo,
36 /// Save the current buffer.
37 Save,
38 /// Quit the editor.
39 Quit,
40 /// No-op — used when a key sequence is pending but not yet complete.
41 Pending,
42}
43
44/// An [`Action`] with an optional repetition count (vim's `5dd`, `10k`).
45#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
46pub struct CountedAction {
47 pub count: u32,
48 pub action: Action,
49}
50
51impl CountedAction {
52 #[must_use]
53 pub fn once(action: Action) -> Self {
54 Self { count: 1, action }
55 }
56
57 #[must_use]
58 pub fn repeated(count: u32, action: Action) -> Self {
59 Self {
60 count: count.max(1),
61 action,
62 }
63 }
64}