mathtex_editor_core/command.rs
1//! Commands the host sends to `Editor::exec` and the outcome it gets back.
2
3use crate::doc::Document;
4use crate::model::{Arrow, FracStyle, Mark, MatrixEnv, ScriptSlot, Symbol, UnderOverSpec, Variant};
5use crate::path::CaretPath;
6
7/// A movement direction.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub enum Dir {
10 /// Left.
11 Left,
12 /// Right.
13 Right,
14 /// Up.
15 Up,
16 /// Down.
17 Down,
18}
19
20/// A side relative to a matrix row or column, or the side a host box is approached from.
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22pub enum Side {
23 /// Before the target.
24 Before,
25 /// After the target.
26 After,
27}
28
29/// A direction in which the caret leaves the formula.
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
31pub enum ExitDir {
32 /// Left.
33 Left,
34 /// Right.
35 Right,
36 /// Up.
37 Up,
38 /// Down.
39 Down,
40}
41
42/// An edge of the whole formula.
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
44pub enum Edge {
45 /// Before the first item.
46 Start,
47 /// After the last item.
48 End,
49}
50
51/// How horizontal motion treats host boxes.
52#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
53pub enum HostBoxPolicy {
54 /// Step over a host box like any atom.
55 #[default]
56 Skip,
57 /// Stop in front of a host box and report it in [`Outcome::entered_host_box`].
58 Enter,
59}
60
61/// A host box the caret would have crossed under [`HostBoxPolicy::Enter`].
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
63pub struct HostBoxEntry {
64 /// The box's token.
65 pub token: u32,
66 /// `Before` when approached moving right, `After` when approached moving left.
67 pub side: Side,
68}
69
70/// An editor command.
71#[derive(Debug, Clone, PartialEq, Eq)]
72pub enum Command {
73 /// Move the caret.
74 Move(Dir),
75 /// Move to the start of the caret's sequence.
76 MoveLineStart,
77 /// Move to the end of the caret's sequence.
78 MoveLineEnd,
79 /// Move to the next empty slot.
80 Tab,
81 /// Move to the previous empty slot.
82 ShiftTab,
83 /// Place the caret, usually at a `Editor::hit_test` result.
84 MoveTo(CaretPath),
85 /// Extend the selection by one step.
86 Extend(Dir),
87 /// Extend the selection to a caret, promoting across structures.
88 ExtendTo(CaretPath),
89 /// Select the whole formula.
90 SelectAll,
91 /// Collapse the selection, or close the menu.
92 Collapse,
93 /// Insert a symbol atom, replacing the selection.
94 InsertAtom(Symbol),
95 /// Insert an opaque host box carrying a host minted token, refused above [`crate::MAX_HOST_TOKEN`].
96 InsertHostBox(u32),
97 /// Insert each character as an atom, spaces are kept only in text slots.
98 InsertText(String),
99 /// Insert a fraction, wrapping the selection into the numerator.
100 InsertFraction(FracStyle),
101 /// Attach a script to the item left of the caret, or wrap the selection as the base.
102 InsertScript(ScriptSlot),
103 /// Insert a big operator with empty limits, replacing the selection.
104 InsertBigOp(Symbol),
105 /// Insert a radical, wrapping the selection into the radicand.
106 InsertSqrt,
107 /// Insert stretchy delimiters, wrapping the selection into the body.
108 InsertDelimiters {
109 /// Opening delimiter.
110 open: char,
111 /// Closing delimiter.
112 close: char,
113 },
114 /// Insert an accent, wrapping the selection into its base.
115 InsertAccent(Mark),
116 /// Insert an under or over construct, wrapping the selection into its base.
117 InsertUnderOver(UnderOverSpec),
118 /// Insert a styled run, wrapping the selection into it.
119 InsertStyled(Variant),
120 /// Insert a matrix, replacing the selection.
121 InsertMatrix {
122 /// Environment.
123 env: MatrixEnv,
124 /// Row count, at least one.
125 rows: usize,
126 /// Column count, at least one.
127 cols: usize,
128 },
129 /// Insert a ratio, wrapping the selection into the first term.
130 InsertRatio,
131 /// Insert an evaluation bar with empty limits, wrapping the selection into its body.
132 InsertEvalBar,
133 /// Insert an extensible arrow with empty labels, wrapping the selection into the label above.
134 InsertLabeledArrow(Arrow),
135 /// Paste a document at the caret, replacing the selection, refused when it fails validation.
136 InsertDocument(Document),
137 /// Delete backward, selecting or opening the menu by a structure, dissolving it from a slot start.
138 DeleteBackward,
139 /// Delete forward, selecting or opening the menu by a structure, dissolving it from a slot end.
140 DeleteForward,
141 /// Insert a matrix row next to the caret's row.
142 MatrixInsertRow(Side),
143 /// Delete the caret's matrix row.
144 MatrixDeleteRow,
145 /// Insert a matrix column next to the caret's column.
146 MatrixInsertCol(Side),
147 /// Delete the caret's matrix column.
148 MatrixDeleteCol,
149 /// Commit the highlighted menu row, or collapse when no menu is open.
150 Confirm,
151 /// Commit a visible menu row by index.
152 MenuSelect(usize),
153 /// When the atoms left of the caret spell `typed`, delete them and run `with`.
154 ReplaceTyped {
155 /// Characters to match, compared through [`Symbol::from_char`].
156 typed: String,
157 /// Commands to run after deleting the match.
158 with: Vec<Command>,
159 },
160 /// Leave the innermost matching delimiters when at their end, else insert the character.
161 CloseDelimiter(char),
162}
163
164/// What a command did.
165#[must_use]
166#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
167pub struct Outcome {
168 /// The document changed and the revision advanced.
169 pub changed: bool,
170 /// The caret or selection moved.
171 pub moved: bool,
172 /// The caret tried to leave the formula in this direction.
173 pub exit: Option<ExitDir>,
174 /// Deleting in an empty formula asks the host to end math mode.
175 pub close: bool,
176 /// Motion stopped in front of a host box under [`HostBoxPolicy::Enter`].
177 pub entered_host_box: Option<HostBoxEntry>,
178 /// The revision after the command.
179 pub revision: u64,
180}