Skip to main content

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}