1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//! `Action`: what the user intends, independent of where the carets are
//! (PLAN 3.5). Key bindings map to actions and macros record them.
use std::fmt;
use serde::{Deserialize, Serialize};
use crate::buffer::BufferId;
use crate::position::VisualCol;
use crate::search::SearchQuery;
use crate::selection::SelectionSet;
use crate::transform::{CaseMode, SortOptions};
use crate::view::ViewId;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum Motion {
/// One grapheme cluster.
Left,
Right,
WordLeft,
WordRight,
/// Smart home: first non-blank of the line, or column 0 if already there.
Home,
LineStart,
LineEnd,
DocStart,
DocEnd,
/// Vertical moves keep a remembered visual column.
Up,
Down,
/// Page moves by the given number of lines (the view's page height).
PageUp(usize),
PageDown(usize),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum Direction {
Up,
Down,
Left,
Right,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum Action {
InsertText(String),
/// Like `InsertText`, but when there are several selections and the text
/// has exactly that many lines, each selection gets one line.
Paste(String),
/// Tab key: a tab character, or spaces to the next tab stop when the
/// editor is set to indent with spaces.
InsertTab,
/// Newline plus the current line's leading whitespace (auto-indent).
InsertNewline,
DeleteBackward,
DeleteForward,
DeleteWordBackward,
DeleteWordForward,
MoveCursor {
motion: Motion,
extend: bool,
},
SelectAll,
SelectWord,
SelectLine,
AddCursorAbove,
AddCursorBelow,
/// Collapse to a caret at the primary selection's head.
CollapseSelections,
/// Replace the selections (mouse clicks and drags). Positions are clamped
/// into the document and onto char boundaries.
SetSelections(SelectionSet),
/// Rectangular selection in visual columns: one selection per line from
/// the anchor corner to the head corner. Lines shorter than the rectangle
/// get an empty selection at their end (no virtual space).
ColumnSelect {
anchor_line: usize,
anchor_col: VisualCol,
head_line: usize,
head_col: VisualCol,
},
/// Grow or shrink the rectangle by moving its head corner (Alt+Shift+
/// arrows); starts a rectangle at the primary caret if there is none.
ColumnExtend(Direction),
/// Paste a rectangular clip: line `i` goes to the caret's visual column
/// on the `i`-th line below it, padding short lines with spaces and
/// adding lines at the end of the document as needed. With several
/// selections or a non-empty one it behaves like `Paste`.
PasteBlock(String),
/// Select the next (or previous) match after the primary selection.
/// Fails with `NotFound` when there is none (macros stop there).
Find {
query: SearchQuery,
backward: bool,
},
/// Replace the primary selection if it is exactly a match, then find
/// the next match.
Replace {
query: SearchQuery,
replacement: String,
},
/// Replace every match (inside the selections with "in selection") as
/// one undo step.
ReplaceAll {
query: SearchQuery,
replacement: String,
},
/// One selection per match.
SelectAllMatches(SearchQuery),
/// Convert each selection (or the caret's line) to a case.
ConvertCase(CaseMode),
/// Sort the selected lines, the rectangle's lines keyed by the text in
/// the rectangle, or the whole document when nothing is selected.
SortLines(SortOptions),
/// Remove trailing spaces and tabs from the selected lines (all lines
/// when nothing is selected).
TrimTrailingWhitespace,
/// Duplicate the caret's line, or each selection.
DuplicateLine,
MoveLinesUp,
MoveLinesDown,
/// Join the selected lines (or the caret's line and the next).
JoinLines,
Undo,
Redo,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ActionError {
UnknownView(ViewId),
UnknownBuffer(BufferId),
InvalidPattern(String),
NotFound,
}
impl fmt::Display for ActionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ActionError::UnknownView(v) => write!(f, "no view with id {}", v.0),
ActionError::UnknownBuffer(b) => write!(f, "no buffer with id {}", b.0),
ActionError::InvalidPattern(e) => write!(f, "invalid search pattern: {e}"),
ActionError::NotFound => f.write_str("no match found"),
}
}
}
impl std::error::Error for ActionError {}