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::{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    /// Paste a document at the caret, replacing the selection, refused when it fails validation.
130    InsertDocument(Document),
131    /// Delete backward, selecting or opening the menu next to a structure first.
132    DeleteBackward,
133    /// Delete forward, selecting or opening the menu next to a structure first.
134    DeleteForward,
135    /// Insert a matrix row next to the caret's row.
136    MatrixInsertRow(Side),
137    /// Delete the caret's matrix row.
138    MatrixDeleteRow,
139    /// Insert a matrix column next to the caret's column.
140    MatrixInsertCol(Side),
141    /// Delete the caret's matrix column.
142    MatrixDeleteCol,
143    /// Commit the highlighted menu row, or collapse when no menu is open.
144    Confirm,
145    /// Commit a visible menu row by index.
146    MenuSelect(usize),
147    /// When the atoms left of the caret spell `typed`, delete them and run `with`.
148    ReplaceTyped {
149        /// Characters to match, compared through [`Symbol::from_char`].
150        typed: String,
151        /// Commands to run after deleting the match.
152        with: Vec<Command>,
153    },
154    /// Leave the innermost matching delimiters when at their end, else insert the character.
155    CloseDelimiter(char),
156}
157
158/// What a command did.
159#[must_use]
160#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
161pub struct Outcome {
162    /// The document changed and the revision advanced.
163    pub changed: bool,
164    /// The caret or selection moved.
165    pub moved: bool,
166    /// The caret tried to leave the formula in this direction.
167    pub exit: Option<ExitDir>,
168    /// Deleting in an empty formula asks the host to end math mode.
169    pub close: bool,
170    /// Motion stopped in front of a host box under [`HostBoxPolicy::Enter`].
171    pub entered_host_box: Option<HostBoxEntry>,
172    /// The revision after the command.
173    pub revision: u64,
174}