1use std::collections::BTreeMap;
5use std::sync::Arc;
6use std::sync::atomic::{AtomicU64, Ordering};
7use std::time::{Duration, Instant};
8
9use crate::action::{Action, ActionError};
10use crate::buffer::{Buffer, BufferId, FileMeta, Indent, LineEdit};
11use crate::changeset::{Bias, ChangeSet};
12use crate::display::DisplayMap;
13use crate::fold::{self, FoldSet};
14use crate::history::Transaction;
15use crate::position::{ByteOffset, byte_to_line_col, line_col_to_byte};
16use crate::resolve::{Resolved, resolve, resolve_search};
17use crate::selection::{Selection, SelectionSet};
18use crate::view::{View, ViewId};
19
20pub trait Clock: Send {
22 fn now(&self) -> Duration;
23}
24
25pub struct SystemClock {
26 origin: Instant,
27}
28
29impl Default for SystemClock {
30 fn default() -> Self {
31 Self {
32 origin: Instant::now(),
33 }
34 }
35}
36
37impl Clock for SystemClock {
38 fn now(&self) -> Duration {
39 self.origin.elapsed()
40 }
41}
42
43#[derive(Clone, Default)]
45pub struct ManualClock(Arc<AtomicU64>);
46
47impl ManualClock {
48 pub fn advance(&self, d: Duration) {
49 self.0.fetch_add(d.as_millis() as u64, Ordering::Relaxed);
50 }
51}
52
53impl Clock for ManualClock {
54 fn now(&self) -> Duration {
55 Duration::from_millis(self.0.load(Ordering::Relaxed))
56 }
57}
58
59#[derive(Clone, Debug)]
61pub struct Settings {
62 pub tab_width: usize,
63 pub use_spaces: bool,
65 pub auto_close: bool,
68 pub smart_indent: bool,
71 pub overtype: bool,
74}
75
76impl Settings {
77 pub fn indent(&self) -> Indent {
79 Indent {
80 use_spaces: self.use_spaces,
81 width: self.tab_width,
82 }
83 }
84}
85
86impl Default for Settings {
87 fn default() -> Self {
88 Self {
89 tab_width: 4,
90 use_spaces: false,
91 auto_close: false,
92 smart_indent: false,
93 overtype: false,
94 }
95 }
96}
97
98pub struct Editor {
99 buffers: BTreeMap<BufferId, Buffer>,
100 views: BTreeMap<ViewId, View>,
101 next_id: u64,
102 pub settings: Settings,
103 clock: Box<dyn Clock>,
104 recording: Option<Vec<Action>>,
105}
106
107impl Default for Editor {
108 fn default() -> Self {
109 Self::with_clock(Box::new(SystemClock::default()))
110 }
111}
112
113impl Editor {
114 pub fn new() -> Self {
115 Self::default()
116 }
117
118 pub fn with_clock(clock: Box<dyn Clock>) -> Self {
119 Self {
120 buffers: BTreeMap::new(),
121 views: BTreeMap::new(),
122 next_id: 1,
123 settings: Settings::default(),
124 clock,
125 recording: None,
126 }
127 }
128
129 fn fresh_id(&mut self) -> u64 {
130 let id = self.next_id;
131 self.next_id += 1;
132 id
133 }
134
135 pub fn add_buffer(&mut self, text: &str, meta: FileMeta) -> BufferId {
136 let id = BufferId(self.fresh_id());
137 let mut buffer = Buffer::new(id, text, meta);
138 buffer.indent = self.settings.indent();
139 self.buffers.insert(id, buffer);
140 id
141 }
142
143 pub fn add_view(&mut self, buffer: BufferId) -> Result<ViewId, ActionError> {
144 if !self.buffers.contains_key(&buffer) {
145 return Err(ActionError::UnknownBuffer(buffer));
146 }
147 let id = ViewId(self.fresh_id());
148 self.views.insert(id, View::new(id, buffer));
149 Ok(id)
150 }
151
152 pub fn remove_view(&mut self, view: ViewId) -> Option<View> {
153 self.views.remove(&view)
154 }
155
156 pub fn remove_buffer(&mut self, buffer: BufferId) -> Option<Buffer> {
158 self.views.retain(|_, v| v.buffer() != buffer);
159 self.buffers.remove(&buffer)
160 }
161
162 pub fn buffer(&self, id: BufferId) -> Option<&Buffer> {
163 self.buffers.get(&id)
164 }
165
166 pub fn buffer_mut(&mut self, id: BufferId) -> Option<&mut Buffer> {
167 self.buffers.get_mut(&id)
168 }
169
170 pub fn view(&self, id: ViewId) -> Option<&View> {
171 self.views.get(&id)
172 }
173
174 pub fn view_mut(&mut self, id: ViewId) -> Option<&mut View> {
175 self.views.get_mut(&id)
176 }
177
178 pub fn buffers(&self) -> impl Iterator<Item = &Buffer> {
179 self.buffers.values()
180 }
181
182 pub fn buffers_mut(&mut self) -> impl Iterator<Item = &mut Buffer> {
183 self.buffers.values_mut()
184 }
185
186 pub fn views(&self) -> impl Iterator<Item = &View> {
187 self.views.values()
188 }
189
190 pub fn views_of(&self, buffer: BufferId) -> impl Iterator<Item = &View> {
192 self.views
193 .values()
194 .filter(move |v| v.buffer() == buffer && !v.is_aux())
195 }
196
197 pub fn add_aux_view(&mut self, buffer: BufferId) -> Result<ViewId, ActionError> {
201 let id = self.add_view(buffer)?;
202 if let Some(v) = self.views.get_mut(&id) {
203 v.set_aux();
204 }
205 Ok(id)
206 }
207
208 pub fn start_recording(&mut self) {
209 self.recording = Some(Vec::new());
210 }
211
212 pub fn is_recording(&self) -> bool {
213 self.recording.is_some()
214 }
215
216 pub fn stop_recording(&mut self) -> Vec<Action> {
217 self.recording.take().unwrap_or_default()
218 }
219
220 pub fn recorded(&self) -> Option<&[Action]> {
222 self.recording.as_deref()
223 }
224
225 pub(crate) fn take_recording(&mut self) -> Option<Vec<Action>> {
226 self.recording.take()
227 }
228
229 pub(crate) fn restore_recording(&mut self, recording: Option<Vec<Action>>) {
230 self.recording = recording;
231 }
232
233 pub fn begin_undo_group(&mut self, view: ViewId) -> Result<(), ActionError> {
236 let (buffer, _) = self.lookup(view)?;
237 self.buffers
238 .get_mut(&buffer)
239 .ok_or(ActionError::UnknownBuffer(buffer))?
240 .history
241 .begin_group();
242 Ok(())
243 }
244
245 pub fn end_undo_group(&mut self, view: ViewId) -> Result<(), ActionError> {
246 let (buffer, _) = self.lookup(view)?;
247 self.buffers
248 .get_mut(&buffer)
249 .ok_or(ActionError::UnknownBuffer(buffer))?
250 .history
251 .end_group();
252 Ok(())
253 }
254
255 fn lookup(&self, view: ViewId) -> Result<(BufferId, &View), ActionError> {
256 let v = self
257 .views
258 .get(&view)
259 .ok_or(ActionError::UnknownView(view))?;
260 if !self.buffers.contains_key(&v.buffer()) {
261 return Err(ActionError::UnknownBuffer(v.buffer()));
262 }
263 Ok((v.buffer(), v))
264 }
265
266 pub fn apply(&mut self, view: ViewId, action: Action) -> Result<(), ActionError> {
270 let (buffer_id, _) = self.lookup(view)?;
271 let read_only = self.buffers.get(&buffer_id).is_some_and(|b| b.read_only);
272 match &action {
273 Action::Undo | Action::Redo if read_only => return Err(ActionError::ReadOnly),
274 Action::Undo => self.undo(view, buffer_id),
275 Action::Redo => self.redo(view, buffer_id),
276 Action::Fold
277 | Action::Unfold
278 | Action::ToggleFold
279 | Action::FoldAll
280 | Action::UnfoldAll
281 | Action::FoldLevel(_)
282 | Action::UnfoldLevel(_) => self.fold_action(view, buffer_id, &action),
283 Action::ToggleBookmark
284 | Action::ClearBookmarks
285 | Action::InverseBookmarks
286 | Action::BookmarkMatches(_) => self.bookmark_action(view, buffer_id, &action)?,
287 _ => {
288 let marked = match action {
289 Action::ReplaceBookmarkedLines(_) => self
290 .buffers
291 .get(&buffer_id)
292 .map(|b| b.bookmarks.lines().to_vec())
293 .unwrap_or_default(),
294 _ => Vec::new(),
295 };
296 let resolved = self.resolve_in(view, buffer_id, &action)??;
297 self.commit(view, buffer_id, resolved)?;
298 if let Some(b) = self.buffers.get_mut(&buffer_id) {
299 let count = b.doc.line_count();
300 match &action {
301 Action::RemoveBookmarkedLines => b.bookmarks.clear(),
304 Action::ReplaceBookmarkedLines(text) => b
305 .bookmarks
306 .set(crate::bookmarks::after_replace(&marked, text), count),
307 _ => {}
308 }
309 }
310 if let Action::ConvertIndentation { to_spaces } = action
311 && let Some(b) = self.buffers.get_mut(&buffer_id)
312 {
313 b.indent.use_spaces = to_spaces;
314 b.indent_set = true;
315 b.indent_mixed = false;
316 }
317 }
318 }
319 self.sync_folds(buffer_id);
320 if let Some(rec) = &mut self.recording
321 && action.is_recordable()
322 {
323 rec.push(action);
324 }
325 Ok(())
326 }
327
328 pub fn apply_unrecorded(&mut self, view: ViewId, action: Action) -> Result<(), ActionError> {
332 let recording = self.recording.take();
333 let result = self.apply(view, action);
334 self.recording = recording;
335 result
336 }
337
338 fn resolve_in(
341 &self,
342 view: ViewId,
343 buffer_id: BufferId,
344 action: &Action,
345 ) -> Result<Result<Resolved, ActionError>, ActionError> {
346 let buffer = self
347 .buffers
348 .get(&buffer_id)
349 .ok_or(ActionError::UnknownBuffer(buffer_id))?;
350 let v = self
351 .views
352 .get(&view)
353 .ok_or(ActionError::UnknownView(view))?;
354 let sels = &v.selections;
355 Ok(match action {
356 Action::Find { .. }
357 | Action::Replace { .. }
358 | Action::ReplaceAll { .. }
359 | Action::SelectAllMatches(_) => resolve_search(action, &buffer.doc, sels),
360 Action::ToggleLineComment
361 | Action::CommentLines
362 | Action::UncommentLines
363 | Action::ToggleBlockComment => {
364 use crate::transform::CommentOp;
365 let syntax = buffer.comments.as_ref();
366 let op = match action {
367 Action::CommentLines => CommentOp::Add,
368 Action::UncommentLines => CommentOp::Remove,
369 _ => CommentOp::Toggle,
370 };
371 let resolved = match (action, syntax) {
372 (Action::ToggleBlockComment, Some(c)) => {
373 c.block.as_ref().map(|(open, close)| {
374 crate::transform::toggle_block_comment(&buffer.doc, sels, open, close)
375 })
376 }
377 (_, Some(c)) => crate::transform::comment_lines(&buffer.doc, sels, c, op),
378 _ => None,
379 };
380 resolved.ok_or(ActionError::NoCommentSyntax)
381 }
382 Action::MultiSelectNext { .. } | Action::MultiSelectAll { .. } => {
383 crate::multiselect::resolve(action, &buffer.doc, sels)
384 }
385 Action::NextBookmark
386 | Action::PrevBookmark
387 | Action::RemoveBookmarkedLines
388 | Action::RemoveUnbookmarkedLines
389 | Action::ReplaceBookmarkedLines(_) => {
390 crate::bookmarks::resolve(action, &buffer.doc, sels, &buffer.bookmarks)
391 }
392 Action::FormatJson { .. }
393 | Action::MinifyJson
394 | Action::Encode(_)
395 | Action::Decode(_) => crate::text_tools::resolve(
396 action,
397 &buffer.doc,
398 sels,
399 buffer.indent,
400 buffer.meta.line_ending,
401 ),
402 _ => {
403 if self.settings.overtype
404 && let Some(r) = crate::overtype::resolve(action, &buffer.doc, sels)
405 {
406 return Ok(Ok(r));
407 }
408 if self.settings.auto_close
409 && let Some(r) = crate::autoclose::resolve(action, &buffer.doc, sels)
410 {
411 return Ok(Ok(r));
412 }
413 if self.settings.smart_indent
414 && let Some(r) = crate::smart_indent::resolve(
415 action,
416 &buffer.doc,
417 sels,
418 buffer.indent,
419 buffer.language.as_deref(),
420 )
421 {
422 return Ok(Ok(r));
423 }
424 let rows = DisplayMap::new(buffer, v);
425 Ok(resolve(action, &buffer.doc, sels, buffer.indent, &rows))
426 }
427 })
428 }
429
430 fn commit(
433 &mut self,
434 view: ViewId,
435 buffer_id: BufferId,
436 resolved: Resolved,
437 ) -> Result<(), ActionError> {
438 match resolved {
439 Resolved::Selections(sels) => {
440 if let Some(b) = self.buffers.get_mut(&buffer_id) {
441 b.history.break_coalescing();
442 }
443 self.set_selections(view, sels);
444 }
445 Resolved::Edit { .. } if self.buffers.get(&buffer_id).is_some_and(|b| b.read_only) => {
446 return Err(ActionError::ReadOnly);
447 }
448 Resolved::Edit {
449 changes,
450 after,
451 kind,
452 } => {
453 let now = self.clock.now();
454 let before = self.views[&view].selections.clone();
455 let Some(buffer) = self.buffers.get_mut(&buffer_id) else {
456 return Err(ActionError::UnknownBuffer(buffer_id));
457 };
458 let inverse = changes.invert(&buffer.doc);
459 let line_edits = apply_changes(buffer, &changes);
460 let rev_before = buffer.revision;
461 let rev_after = buffer.next_revision;
462 buffer.next_revision += 1;
463 buffer.revision = rev_after;
464 buffer.history.push(
465 Transaction {
466 changes: changes.clone(),
467 inverse,
468 before,
469 after: after.clone(),
470 },
471 kind,
472 rev_before,
473 rev_after,
474 now,
475 );
476 self.set_selections(view, after);
477 self.map_other_views(buffer_id, view, &changes);
478 self.map_folds(buffer_id, &changes, &line_edits);
479 }
480 }
481 Ok(())
482 }
483
484 pub fn reload_buffer(
489 &mut self,
490 buffer: BufferId,
491 text: &str,
492 meta: FileMeta,
493 ) -> Result<(), ActionError> {
494 let view = self
495 .views_of(buffer)
496 .next()
497 .map(View::id)
498 .ok_or(ActionError::UnknownBuffer(buffer))?;
499 let b = self
500 .buffers
501 .get(&buffer)
502 .ok_or(ActionError::UnknownBuffer(buffer))?;
503 if b.doc.to_string() != text {
504 let new_doc = crate::text::Document::new(text);
505 let remap = |p: ByteOffset| {
506 let lc = byte_to_line_col(&b.doc, p);
507 let mut q = line_col_to_byte(&new_doc, lc);
508 while !new_doc.is_char_boundary(q) {
509 q.0 -= 1;
510 }
511 q
512 };
513 let after = self.views[&view]
514 .selections
515 .map(|s| Selection::new(remap(s.anchor), remap(s.head)));
516 let changes = ChangeSet::new(
517 b.doc.len(),
518 vec![crate::changeset::Edit::new(
519 ByteOffset(0),
520 b.doc.len(),
521 text,
522 )],
523 );
524 let read_only = self
525 .buffers
526 .get_mut(&buffer)
527 .map(|b| std::mem::replace(&mut b.read_only, false));
528 let committed = self.commit(
529 view,
530 buffer,
531 Resolved::Edit {
532 changes,
533 after,
534 kind: crate::history::EditKind::Other,
535 },
536 );
537 if let (Some(b), Some(read_only)) = (self.buffers.get_mut(&buffer), read_only) {
538 b.read_only = read_only;
539 }
540 committed?;
541 }
542 if let Some(b) = self.buffers.get_mut(&buffer) {
543 b.meta = meta;
544 b.mark_saved();
545 }
546 self.sync_folds(buffer);
547 Ok(())
548 }
549
550 fn undo(&mut self, view: ViewId, buffer_id: BufferId) {
551 let Some(buffer) = self.buffers.get_mut(&buffer_id) else {
552 return;
553 };
554 let Some(step) = buffer.history.pop_undo() else {
555 return;
556 };
557 let inverses: Vec<ChangeSet> = step.txns.iter().rev().map(|t| t.inverse.clone()).collect();
558 let line_edits: Vec<Vec<LineEdit>> = inverses
559 .iter()
560 .map(|inv| apply_changes(buffer, inv))
561 .collect();
562 buffer.revision = step.rev_before;
563 let sels = step.txns[0].before.clone();
564 buffer.history.push_redo(step);
565 self.set_selections(view, sels);
566 for (inv, edits) in inverses.iter().zip(&line_edits) {
567 self.map_other_views(buffer_id, view, inv);
568 self.map_folds(buffer_id, inv, edits);
569 }
570 }
571
572 fn redo(&mut self, view: ViewId, buffer_id: BufferId) {
573 let Some(buffer) = self.buffers.get_mut(&buffer_id) else {
574 return;
575 };
576 let Some(step) = buffer.history.pop_redo() else {
577 return;
578 };
579 let changes: Vec<ChangeSet> = step.txns.iter().map(|t| t.changes.clone()).collect();
580 let line_edits: Vec<Vec<LineEdit>> =
581 changes.iter().map(|cs| apply_changes(buffer, cs)).collect();
582 buffer.revision = step.rev_after;
583 let sels = step.txns[step.txns.len() - 1].after.clone();
584 buffer.history.push_undo(step);
585 self.set_selections(view, sels);
586 for (cs, edits) in changes.iter().zip(&line_edits) {
587 self.map_other_views(buffer_id, view, cs);
588 self.map_folds(buffer_id, cs, edits);
589 }
590 }
591
592 fn set_selections(&mut self, view: ViewId, sels: SelectionSet) {
593 if let Some(v) = self.views.get_mut(&view) {
594 v.selections = sels;
595 }
596 }
597
598 fn map_folds(&mut self, buffer: BufferId, changes: &ChangeSet, line_edits: &[LineEdit]) {
603 for v in self.views.values_mut() {
604 if v.buffer() != buffer {
605 continue;
606 }
607 if !v.folds.is_empty() {
608 v.folds.map(changes);
609 }
610 v.folds.filter_line_edits(line_edits);
611 }
612 }
613
614 pub fn append_unrecorded(
618 &mut self,
619 buffer_id: BufferId,
620 text: &str,
621 ) -> Result<(), ActionError> {
622 let buffer = self
623 .buffers
624 .get_mut(&buffer_id)
625 .ok_or(ActionError::UnknownBuffer(buffer_id))?;
626 if text.is_empty() {
627 return Ok(());
628 }
629 let end = buffer.doc.len();
630 let changes = ChangeSet::new(end, vec![crate::changeset::Edit::new(end, end, text)]);
631 let clean = !buffer.is_dirty();
632 let line_edits = apply_changes(buffer, &changes);
633 let (old, new) = (buffer.revision, buffer.next_revision);
634 buffer.history.extend_base(text.len(), old, new);
635 buffer.revision = new;
636 buffer.next_revision += 1;
637 if clean {
638 buffer.mark_saved();
639 }
640 for v in self.views.values_mut() {
641 if v.buffer() == buffer_id {
642 v.selections = v.selections.map(|s| Selection {
643 anchor: changes.map_position(s.anchor, Bias::After),
644 head: changes.map_position(s.head, Bias::After),
645 goal: None,
646 });
647 }
648 }
649 self.map_folds(buffer_id, &changes, &line_edits);
650 self.sync_folds(buffer_id);
651 Ok(())
652 }
653
654 pub fn set_filter(&mut self, view: ViewId, shown: Option<&[usize]>) {
659 let Some(v) = self.views.get_mut(&view) else {
660 return;
661 };
662 let Some(b) = self.buffers.get(&v.buffer()) else {
663 return;
664 };
665 let doc = &b.doc;
666 let count = doc.line_count();
667 let Some(shown) = shown else {
668 v.folds.set_filter(None, count);
669 return;
670 };
671 let caret_line = [doc.line_of(v.selections.primary().head)];
672 let in_doc = shown.partition_point(|&l| l < count);
673 let shown = if in_doc == 0 {
674 &caret_line[..]
675 } else {
676 &shown[..in_doc]
677 };
678 v.folds.set_filter(Some(shown), count);
679 let folds = &v.folds;
680 let moved = v.selections.map(|s| {
681 let line = doc.line_of(s.head);
682 if !folds.filter_hides(line) {
683 return s.clone();
684 }
685 let after = shown.partition_point(|&l| l < line);
686 let target = shown
687 .get(after)
688 .or_else(|| after.checked_sub(1).and_then(|i| shown.get(i)))
689 .copied()
690 .unwrap_or(0)
691 .min(count - 1);
692 Selection::caret(doc.line_start(target))
693 });
694 v.selections = moved;
695 }
696
697 pub fn filter_appended(&mut self, view: ViewId, from: usize, shown: &[usize]) {
701 let Some(v) = self.views.get_mut(&view) else {
702 return;
703 };
704 let Some(b) = self.buffers.get(&v.buffer()) else {
705 return;
706 };
707 let doc = &b.doc;
708 let mut lines = shown.to_vec();
709 lines.extend(
710 v.selections
711 .ranges()
712 .iter()
713 .map(|s| doc.line_of(s.head))
714 .filter(|&l| l >= from),
715 );
716 lines.sort_unstable();
717 lines.dedup();
718 v.folds.set_filter_from(from, &lines, doc.line_count());
719 }
720
721 pub fn caret_lines(&self, view: ViewId) -> Vec<usize> {
723 let Some(v) = self.views.get(&view) else {
724 return Vec::new();
725 };
726 let Some(b) = self.buffers.get(&v.buffer()) else {
727 return Vec::new();
728 };
729 let mut lines: Vec<usize> = v
730 .selections
731 .ranges()
732 .iter()
733 .map(|s| b.doc.line_of(s.head))
734 .collect();
735 lines.dedup();
736 lines
737 }
738
739 fn sync_folds(&mut self, buffer: BufferId) {
742 let Some(doc) = self.buffers.get(&buffer).map(|b| &b.doc) else {
743 return;
744 };
745 for v in self.views.values_mut() {
746 if v.buffer() != buffer {
747 continue;
748 }
749 v.folds.relines(doc);
752 if v.folds.has_filter() {
755 let lines: Vec<usize> = v
756 .selections
757 .ranges()
758 .iter()
759 .map(|s| doc.line_of(s.head))
760 .filter(|&l| v.folds.filter_hides(l))
761 .collect();
762 v.folds.unfilter(&lines);
763 }
764 if v.folds.is_empty() {
765 continue;
766 }
767 let hidden: Vec<usize> = v
768 .selections
769 .ranges()
770 .iter()
771 .map(|s| doc.line_of(s.head))
772 .filter(|&l| v.folds.is_hidden(l))
773 .collect();
774 if !hidden.is_empty() {
775 v.folds
776 .retain(|header, last| !hidden.iter().any(|&l| header < l && l <= last));
777 }
778 }
779 }
780
781 pub fn fold_at(&mut self, view: ViewId, line: usize) -> bool {
784 let Some(v) = self.views.get_mut(&view) else {
785 return false;
786 };
787 let Some(b) = self.buffers.get(&v.buffer()) else {
788 return false;
789 };
790 let tab_width = b.indent.width;
791 let Some(last) = fold::region(&b.doc, line, b.fold_strategy, tab_width) else {
792 return false;
793 };
794 v.folds.insert(&b.doc, [(line, last)]);
795 reveal_carets(&b.doc, v);
796 true
797 }
798
799 pub fn unfold_at(&mut self, view: ViewId, line: usize) -> bool {
801 self.views
802 .get_mut(&view)
803 .is_some_and(|v| v.folds.remove(line))
804 }
805
806 pub fn toggle_fold_at(&mut self, view: ViewId, line: usize) -> bool {
808 self.unfold_at(view, line) || self.fold_at(view, line)
809 }
810
811 fn fold_action(&mut self, view: ViewId, buffer: BufferId, action: &Action) {
812 let (Some(v), Some(b)) = (self.views.get_mut(&view), self.buffers.get(&buffer)) else {
813 return;
814 };
815 let tab_width = b.indent.width;
816 let (doc, strategy) = (&b.doc, b.fold_strategy);
817 let caret = doc.line_of(v.selections.primary().head);
818 let around = || fold::enclosing(doc, caret, strategy, tab_width);
819 match action {
820 Action::Fold => {
821 if let Some(r) = around() {
822 v.folds.insert(doc, [r]);
823 }
824 }
825 Action::ToggleFold => {
826 if !v.folds.remove(caret)
827 && let Some(r) = around()
828 {
829 v.folds.insert(doc, [r]);
830 }
831 }
832 Action::Unfold => {
833 if !v.folds.remove(caret)
834 && let Some((header, last)) = around()
835 {
836 v.folds.retain(|h, _| h < header || h > last);
837 }
838 }
839 Action::FoldAll => {
840 let all = fold::regions(doc, strategy, tab_width);
841 v.folds.insert(doc, all.iter().map(|r| (r.header, r.last)));
842 }
843 Action::UnfoldAll => v.folds = FoldSet::default(),
844 Action::FoldLevel(n) => {
845 let all = fold::regions(doc, strategy, tab_width);
846 let level = all.iter().filter(|r| r.level == *n);
847 v.folds.insert(doc, level.map(|r| (r.header, r.last)));
848 }
849 Action::UnfoldLevel(n) => {
850 let level: std::collections::HashSet<usize> =
851 fold::regions(doc, strategy, tab_width)
852 .into_iter()
853 .filter(|r| r.level == *n)
854 .map(|r| r.header)
855 .collect();
856 v.folds.retain(|h, _| !level.contains(&h));
857 }
858 _ => {}
859 }
860 reveal_carets(doc, v);
861 }
862
863 fn bookmark_action(
865 &mut self,
866 view: ViewId,
867 buffer: BufferId,
868 action: &Action,
869 ) -> Result<(), ActionError> {
870 let (Some(v), Some(b)) = (self.views.get(&view), self.buffers.get_mut(&buffer)) else {
871 return Err(ActionError::UnknownView(view));
872 };
873 let count = b.doc.line_count();
874 match action {
875 Action::ToggleBookmark => {
876 let lines = crate::bookmarks::caret_lines(&b.doc, &v.selections);
877 if lines.iter().all(|&l| b.bookmarks.contains(l)) {
878 for l in lines {
879 b.bookmarks.remove(l);
880 }
881 } else {
882 for l in lines {
883 b.bookmarks.insert(l);
884 }
885 }
886 }
887 Action::ClearBookmarks => b.bookmarks.clear(),
888 Action::InverseBookmarks => b.bookmarks.invert(count),
889 Action::BookmarkMatches(query) => {
890 let searcher = crate::search::Searcher::new(query)
891 .map_err(|e| ActionError::InvalidPattern(e.0))?;
892 let matches = searcher.find_in(&b.doc, &v.selections);
893 if matches.is_empty() {
894 return Err(ActionError::NotFound);
895 }
896 let found = matches.iter().map(|m| b.doc.line_of(m.start));
897 let all: Vec<usize> = b.bookmarks.lines().iter().copied().chain(found).collect();
898 b.bookmarks.set(all, count);
899 }
900 _ => {}
901 }
902 Ok(())
903 }
904
905 fn map_other_views(&mut self, buffer: BufferId, except: ViewId, changes: &ChangeSet) {
910 for v in self.views.values_mut() {
911 if v.buffer() != buffer {
912 continue;
913 }
914 v.begin_select = v.begin_select.map(|p| changes.map_position(p, Bias::After));
916 if v.id() != except {
917 v.selections = v.selections.map(|s| Selection {
918 anchor: changes.map_position(s.anchor, Bias::Before),
919 head: changes.map_position(s.head, Bias::Before),
920 goal: s.goal,
921 });
922 }
923 }
924 }
925}
926
927fn reveal_carets(doc: &crate::text::Document, v: &mut View) {
930 let folds = &v.folds;
931 if folds.is_empty() {
932 return;
933 }
934 let moved = v.selections.map(|s| {
935 let Some((start, _)) = folds.fold_hidden_range(doc.line_of(s.head)) else {
936 return s.clone();
937 };
938 let head = doc.line_end(start - 1);
939 if s.is_empty() {
940 Selection::caret(head)
941 } else {
942 Selection::new(s.anchor, head)
943 }
944 });
945 v.selections = moved;
946}
947
948fn apply_changes(buffer: &mut Buffer, changes: &ChangeSet) -> Vec<LineEdit> {
951 let mut edits = Vec::with_capacity(changes.edits().len());
954 let marked = !buffer.bookmarks.is_empty();
955 let mut mark_edits = Vec::new();
956 for e in changes.edits().iter().rev() {
957 let start = buffer.doc.line_of(e.start);
958 let new_lines = e.text.bytes().filter(|&b| b == b'\n').count();
959 let edit = LineEdit {
960 start,
961 old_end: buffer.doc.line_of(e.end),
962 new_end: start + new_lines,
963 };
964 if marked {
965 mark_edits.push(crate::bookmarks::EditLines {
966 start,
967 old_end: edit.old_end,
968 new_lines,
969 at_line_start: buffer.doc.line_start(start) == e.start,
970 insertion: e.start == e.end,
971 });
972 }
973 buffer.record_line_edit(edit);
974 edits.push(edit);
975 }
976 changes.apply(&mut buffer.doc);
977 if marked {
978 mark_edits.reverse();
979 let count = buffer.doc.line_count();
980 buffer.bookmarks.map(&mark_edits, count);
981 }
982 edits
983}