1use super::*;
4
5impl Editor {
6 pub(super) fn turn_into(&mut self, ix: usize, kind: BlockKind, cx: &mut Context<Self>) {
12 self.edit(EditKind::Structure, cx, |this| {
13 let held = this.doc.blocks[ix]
17 .text_at(Part::Body)
18 .map_or(0, |text| text.text.len());
19 this.doc.edit_at(Cursor::new(ix, Part::Body, 0), |text| {
20 *text = Text::default()
21 });
22 this.doc.set_kind(ix, kind);
23 let part = this.doc.blocks[ix].parts().first().copied();
26 let at = match part {
27 Some(part) => Cursor::new(ix, part, 0),
28 None => {
29 if this.doc.blocks.len() <= ix + 1 {
30 this.doc
31 .blocks
32 .push(markdown::Block::new(BlockKind::Paragraph(Text::default())));
33 }
34 Cursor::new(ix + 1, Part::Body, 0)
35 }
36 };
37 this.selection = Selection::at(at.clamp(&this.doc));
38 vec![Delta::Spliced(Splice {
39 removed: Selection::new(
40 Cursor::new(ix, Part::Body, 0),
41 Cursor::new(ix, Part::Body, held),
42 ),
43 caret: Cursor::new(ix, Part::Body, 0),
44 blocks: 0,
45 })]
46 });
47 }
48
49 pub(super) fn undo(&mut self, _: &Undo, _: &mut Window, cx: &mut Context<Self>) {
50 if let Some(step) = self
51 .history
52 .undo(self.mode, &self.doc, self.selection, &self.anchors)
53 {
54 self.restore(step, cx);
55 }
56 }
57
58 pub(super) fn redo(&mut self, _: &Redo, _: &mut Window, cx: &mut Context<Self>) {
59 if let Some(step) = self
60 .history
61 .redo(self.mode, &self.doc, self.selection, &self.anchors)
62 {
63 self.restore(step, cx);
64 }
65 }
66
67 pub(super) fn restore(&mut self, step: crate::history::Step, cx: &mut Context<Self>) {
73 self.doc = step.doc;
74 self.selection = step.selection.clamp(&self.doc);
75 self.caret_moved();
76 self.anchors = step.anchors;
77 if step.mode != self.mode {
78 self.mode = step.mode;
79 self.dismiss_menus();
80 cx.emit(EditorEvent::ModeChanged(step.mode));
81 }
82 cx.emit(EditorEvent::Changed);
83 cx.notify();
84 }
85
86 pub fn move_block(&mut self, ix: usize, delta: isize, cx: &mut Context<Self>) {
91 if !self.blocks() {
92 return;
93 }
94 self.edit(EditKind::Structure, cx, |this| {
95 let caret = this.cursor();
96 let at = this.doc.subtree(ix);
97 let Some(to) = this.doc.move_block(ix, delta) else {
98 return vec![];
99 };
100 let block = to + caret.block.saturating_sub(ix);
103 this.selection = Selection::at(Cursor { block, ..caret }.clamp(&this.doc));
104 vec![Delta::Moved { at, to: Some(to) }]
105 });
106 }
107
108 pub fn duplicate_block(&mut self, ix: usize, cx: &mut Context<Self>) {
109 if !self.blocks() {
110 return;
111 }
112 self.edit(EditKind::Structure, cx, |this| {
113 let span = this.doc.subtree(ix);
114 let Some(copy) = this.doc.duplicate(ix) else {
115 return vec![];
116 };
117 this.selection = Selection::at(Cursor::new(copy, Part::Body, 0).clamp(&this.doc));
118 vec![Delta::Opened {
119 at: copy,
120 count: span.len(),
121 }]
122 });
123 }
124
125 pub fn remove_block(&mut self, ix: usize, cx: &mut Context<Self>) {
126 if !self.blocks() {
127 return;
128 }
129 self.edit(EditKind::Structure, cx, |this| {
130 let at = this.doc.subtree(ix);
131 this.doc.remove_block(ix);
132 this.selection =
133 Selection::at(Cursor::new(ix.saturating_sub(1), Part::Body, 0).clamp(&this.doc));
134 vec![Delta::Moved { at, to: None }]
135 });
136 }
137
138 pub fn set_language(&mut self, ix: usize, language: Option<String>, cx: &mut Context<Self>) {
140 if !self.blocks() {
141 return;
142 }
143 self.edit(EditKind::Structure, cx, |this| {
144 this.doc.set_language(ix, language);
145 vec![]
146 });
147 }
148
149 pub fn set_block(&mut self, ix: usize, kind: BlockKind, cx: &mut Context<Self>) {
152 if !self.blocks() {
153 return;
154 }
155 self.edit(EditKind::Structure, cx, |this| {
156 this.doc.set_kind(ix, kind);
157 this.selection = this.selection.clamp(&this.doc);
158 vec![]
159 });
160 }
161
162 pub fn toggle_task(&mut self, ix: usize, cx: &mut Context<Self>) {
169 if !self.blocks() {
170 return;
171 }
172 let checked = match self.doc.blocks.get(ix).map(|block| &block.kind) {
173 Some(BlockKind::Task { checked, .. }) => !checked,
174 _ => return,
175 };
176 self.edit(EditKind::Structure, cx, |this| {
177 if let Some(BlockKind::Task { checked: at, .. }) =
178 this.doc.blocks.get_mut(ix).map(|block| &mut block.kind)
179 {
180 *at = checked;
181 }
182 vec![]
183 });
184 self.reveal = false;
189 }
190
191 pub fn add_row(&mut self, ix: usize, row: usize, cx: &mut Context<Self>) {
194 if !self.blocks() || !matches!(self.kind_at(ix), Some(BlockKind::Table { .. })) {
195 return;
196 }
197 self.edit(EditKind::Structure, cx, |this| {
198 this.doc.insert_row(ix, row);
199 let row = row.max(1);
200 this.selection = Selection::at(Cursor::new(ix, Part::Cell { row, column: 0 }, 0));
201 vec![Delta::Cells {
202 block: ix,
203 row: Some(row),
204 column: None,
205 }]
206 });
207 }
208
209 pub fn add_column(&mut self, ix: usize, column: usize, cx: &mut Context<Self>) {
212 if !self.blocks() || !matches!(self.kind_at(ix), Some(BlockKind::Table { .. })) {
213 return;
214 }
215 let row = match self.cursor() {
216 Cursor {
217 block,
218 part: Part::Cell { row, .. },
219 ..
220 } if block == ix => row,
221 _ => self.doc.blocks[ix]
222 .parts()
223 .first()
224 .map_or(0, |part| match part {
225 Part::Cell { row, .. } => *row,
226 _ => 0,
227 }),
228 };
229 self.edit(EditKind::Structure, cx, |this| {
230 this.doc.insert_column(ix, column);
231 this.selection = Selection::at(Cursor::new(ix, Part::Cell { row, column }, 0));
232 vec![Delta::Cells {
233 block: ix,
234 row: None,
235 column: Some(column),
236 }]
237 });
238 }
239
240 pub(super) fn step_cell(&mut self, forward: bool, cx: &mut Context<Self>) -> bool {
243 let at = self.cursor();
244 let Part::Cell { row, .. } = at.part else {
245 return false;
246 };
247 let parts = self.doc.blocks[at.block].parts();
248 let Some(here) = parts.iter().position(|part| *part == at.part) else {
249 return false;
250 };
251 let next = match forward {
252 true => parts.get(here + 1),
253 false => here.checked_sub(1).and_then(|ix| parts.get(ix)),
254 };
255 match next {
256 Some(part) => {
257 let end = Cursor::new(at.block, *part, usize::MAX).clamp(&self.doc);
258 self.head_to(end, false);
259 cx.notify();
260 }
261 None if forward => self.add_row(at.block, row + 1, cx),
262 None => {}
263 }
264 true
265 }
266
267 pub(super) fn cell_down(&mut self, cx: &mut Context<Self>) -> bool {
270 let at = self.cursor();
271 let Part::Cell { row, column } = at.part else {
272 return false;
273 };
274 let below = Part::Cell {
275 row: row + 1,
276 column,
277 };
278 if self.doc.blocks[at.block].text_at(below).is_none() {
279 self.add_row(at.block, row + 1, cx);
280 if column > 0 {
281 self.head_to(Cursor::new(at.block, below, 0).clamp(&self.doc), false);
282 }
283 return true;
284 }
285 let end = Cursor::new(at.block, below, usize::MAX).clamp(&self.doc);
286 self.head_to(end, false);
287 cx.notify();
288 true
289 }
290
291 pub fn remove_row(&mut self, ix: usize, row: usize, cx: &mut Context<Self>) {
293 self.remove_line(ix, Line::Row(row), cx);
294 }
295
296 pub fn remove_column(&mut self, ix: usize, column: usize, cx: &mut Context<Self>) {
298 self.remove_line(ix, Line::Column(column), cx);
299 }
300
301 fn remove_line(&mut self, ix: usize, line: Line, cx: &mut Context<Self>) {
302 if !self.blocks() {
303 return;
304 }
305 let Some(BlockKind::Table { header, rows, .. }) = self.kind_at(ix) else {
306 return;
307 };
308 let width = rows
309 .iter()
310 .map(Vec::len)
311 .chain([header.len()])
312 .max()
313 .unwrap_or(0);
314 let removable = match line {
315 Line::Row(row) => (1..=rows.len()).contains(&row),
316 Line::Column(column) => width > 1 && column < width,
317 };
318 if !removable {
319 return;
320 }
321 self.edit(EditKind::Structure, cx, |this| {
322 match line {
323 Line::Row(row) => this.doc.remove_row(ix, row),
324 Line::Column(column) => this.doc.remove_column(ix, column),
325 };
326 this.selection = this.selection.clamp(&this.doc);
327 let (row, column) = match line {
328 Line::Row(row) => (Some(row), None),
329 Line::Column(column) => (None, Some(column)),
330 };
331 vec![Delta::CellsRemoved {
332 block: ix,
333 row,
334 column,
335 }]
336 });
337 }
338
339 fn kind_at(&self, ix: usize) -> Option<&BlockKind> {
340 self.doc.blocks.get(ix).map(|block| &block.kind)
341 }
342}