1mod anchor;
2mod point;
3pub mod rope;
4mod selection;
5
6pub use anchor::*;
7use parking_lot::Mutex;
8pub use point::*;
9pub use rope::{Chunks, Rope, TextSummary};
10use seahash::SeaHasher;
11pub use selection::*;
12use similar::{ChangeTag, TextDiff};
13use tree_sitter::{InputEdit, Parser, QueryCursor};
14
15use crate::{
16 language::{Language, Tree},
17 operation_queue::{self, OperationQueue},
18 settings::{StyleId, ThemeMap},
19 sum_tree::{self, FilterCursor, SumTree},
20 time::{self, ReplicaId},
21 util::Bias,
22 worktree::FileHandle,
23};
24use anyhow::{anyhow, Result};
25use gpui::{AppContext, Entity, ModelContext, Task};
26use lazy_static::lazy_static;
27use std::{
28 cell::RefCell,
29 cmp,
30 hash::BuildHasher,
31 iter::Iterator,
32 ops::{Deref, DerefMut, Range},
33 str,
34 sync::Arc,
35 time::{Duration, Instant, SystemTime, UNIX_EPOCH},
36};
37
38const UNDO_GROUP_INTERVAL: Duration = Duration::from_millis(300);
39
40#[derive(Clone, Default)]
41struct DeterministicState;
42
43impl BuildHasher for DeterministicState {
44 type Hasher = SeaHasher;
45
46 fn build_hasher(&self) -> Self::Hasher {
47 SeaHasher::new()
48 }
49}
50
51#[cfg(test)]
52type HashMap<K, V> = std::collections::HashMap<K, V, DeterministicState>;
53
54#[cfg(test)]
55type HashSet<T> = std::collections::HashSet<T, DeterministicState>;
56
57#[cfg(not(test))]
58type HashMap<K, V> = std::collections::HashMap<K, V>;
59
60#[cfg(not(test))]
61type HashSet<T> = std::collections::HashSet<T>;
62
63thread_local! {
64 static PARSER: RefCell<Parser> = RefCell::new(Parser::new());
65}
66
67lazy_static! {
68 static ref QUERY_CURSORS: Mutex<Vec<QueryCursor>> = Default::default();
69}
70
71struct QueryCursorHandle(Option<QueryCursor>);
72
73impl QueryCursorHandle {
74 fn new() -> Self {
75 QueryCursorHandle(Some(
76 QUERY_CURSORS
77 .lock()
78 .pop()
79 .unwrap_or_else(|| QueryCursor::new()),
80 ))
81 }
82}
83
84impl Deref for QueryCursorHandle {
85 type Target = QueryCursor;
86
87 fn deref(&self) -> &Self::Target {
88 self.0.as_ref().unwrap()
89 }
90}
91
92impl DerefMut for QueryCursorHandle {
93 fn deref_mut(&mut self) -> &mut Self::Target {
94 self.0.as_mut().unwrap()
95 }
96}
97
98impl Drop for QueryCursorHandle {
99 fn drop(&mut self) {
100 let mut cursor = self.0.take().unwrap();
101 cursor.set_byte_range(0..usize::MAX);
102 cursor.set_point_range(Point::zero().into()..Point::MAX.into());
103 QUERY_CURSORS.lock().push(cursor)
104 }
105}
106
107pub struct Buffer {
108 fragments: SumTree<Fragment>,
109 visible_text: Rope,
110 deleted_text: Rope,
111 pub version: time::Global,
112 saved_version: time::Global,
113 saved_mtime: SystemTime,
114 last_edit: time::Local,
115 undo_map: UndoMap,
116 history: History,
117 file: Option<FileHandle>,
118 language: Option<Arc<Language>>,
119 syntax_tree: Mutex<Option<SyntaxTree>>,
120 is_parsing: bool,
121 selections: HashMap<SelectionSetId, Arc<[Selection]>>,
122 pub selections_last_update: SelectionsVersion,
123 deferred_ops: OperationQueue<Operation>,
124 deferred_replicas: HashSet<ReplicaId>,
125 replica_id: ReplicaId,
126 local_clock: time::Local,
127 lamport_clock: time::Lamport,
128}
129
130#[derive(Clone)]
131struct SyntaxTree {
132 tree: Tree,
133 parsed: bool,
134 version: time::Global,
135}
136
137#[derive(Clone)]
138struct Transaction {
139 start: time::Global,
140 buffer_was_dirty: bool,
141 edits: Vec<time::Local>,
142 selections_before: Option<(SelectionSetId, Arc<[Selection]>)>,
143 selections_after: Option<(SelectionSetId, Arc<[Selection]>)>,
144 first_edit_at: Instant,
145 last_edit_at: Instant,
146}
147
148#[derive(Clone)]
149pub struct History {
150 // TODO: Turn this into a String or Rope, maybe.
151 pub base_text: Arc<str>,
152 ops: HashMap<time::Local, EditOperation>,
153 undo_stack: Vec<Transaction>,
154 redo_stack: Vec<Transaction>,
155 transaction_depth: usize,
156 group_interval: Duration,
157}
158
159impl History {
160 pub fn new(base_text: Arc<str>) -> Self {
161 Self {
162 base_text,
163 ops: Default::default(),
164 undo_stack: Vec::new(),
165 redo_stack: Vec::new(),
166 transaction_depth: 0,
167 group_interval: UNDO_GROUP_INTERVAL,
168 }
169 }
170
171 fn push(&mut self, op: EditOperation) {
172 self.ops.insert(op.timestamp.local(), op);
173 }
174
175 fn start_transaction(
176 &mut self,
177 start: time::Global,
178 buffer_was_dirty: bool,
179 selections: Option<(SelectionSetId, Arc<[Selection]>)>,
180 now: Instant,
181 ) {
182 self.transaction_depth += 1;
183 if self.transaction_depth == 1 {
184 self.undo_stack.push(Transaction {
185 start,
186 buffer_was_dirty,
187 edits: Vec::new(),
188 selections_before: selections,
189 selections_after: None,
190 first_edit_at: now,
191 last_edit_at: now,
192 });
193 }
194 }
195
196 fn end_transaction(
197 &mut self,
198 selections: Option<(SelectionSetId, Arc<[Selection]>)>,
199 now: Instant,
200 ) -> Option<&Transaction> {
201 assert_ne!(self.transaction_depth, 0);
202 self.transaction_depth -= 1;
203 if self.transaction_depth == 0 {
204 let transaction = self.undo_stack.last_mut().unwrap();
205 transaction.selections_after = selections;
206 transaction.last_edit_at = now;
207 Some(transaction)
208 } else {
209 None
210 }
211 }
212
213 fn group(&mut self) {
214 let mut new_len = self.undo_stack.len();
215 let mut transactions = self.undo_stack.iter_mut();
216
217 if let Some(mut transaction) = transactions.next_back() {
218 for prev_transaction in transactions.next_back() {
219 if transaction.first_edit_at - prev_transaction.last_edit_at <= self.group_interval
220 {
221 prev_transaction.edits.append(&mut transaction.edits);
222 prev_transaction.last_edit_at = transaction.last_edit_at;
223 prev_transaction.selections_after = transaction.selections_after.take();
224 transaction = prev_transaction;
225 new_len -= 1;
226 } else {
227 break;
228 }
229 }
230 }
231
232 self.undo_stack.truncate(new_len);
233 }
234
235 fn push_undo(&mut self, edit_id: time::Local) {
236 assert_ne!(self.transaction_depth, 0);
237 self.undo_stack.last_mut().unwrap().edits.push(edit_id);
238 }
239
240 fn pop_undo(&mut self) -> Option<&Transaction> {
241 assert_eq!(self.transaction_depth, 0);
242 if let Some(transaction) = self.undo_stack.pop() {
243 self.redo_stack.push(transaction);
244 self.redo_stack.last()
245 } else {
246 None
247 }
248 }
249
250 fn pop_redo(&mut self) -> Option<&Transaction> {
251 assert_eq!(self.transaction_depth, 0);
252 if let Some(transaction) = self.redo_stack.pop() {
253 self.undo_stack.push(transaction);
254 self.undo_stack.last()
255 } else {
256 None
257 }
258 }
259}
260
261#[derive(Clone, Default, Debug)]
262struct UndoMap(HashMap<time::Local, Vec<UndoOperation>>);
263
264impl UndoMap {
265 fn insert(&mut self, undo: UndoOperation) {
266 self.0.entry(undo.edit_id).or_default().push(undo);
267 }
268
269 fn is_undone(&self, edit_id: time::Local) -> bool {
270 self.undo_count(edit_id) % 2 == 1
271 }
272
273 fn was_undone(&self, edit_id: time::Local, version: &time::Global) -> bool {
274 let undo_count = self
275 .0
276 .get(&edit_id)
277 .unwrap_or(&Vec::new())
278 .iter()
279 .filter(|undo| version.observed(undo.id))
280 .map(|undo| undo.count)
281 .max()
282 .unwrap_or(0);
283 undo_count % 2 == 1
284 }
285
286 fn undo_count(&self, edit_id: time::Local) -> u32 {
287 self.0
288 .get(&edit_id)
289 .unwrap_or(&Vec::new())
290 .iter()
291 .map(|undo| undo.count)
292 .max()
293 .unwrap_or(0)
294 }
295}
296
297struct Edits<'a, F: Fn(&FragmentSummary) -> bool> {
298 deleted_text: &'a Rope,
299 cursor: FilterCursor<'a, F, Fragment, FragmentTextSummary>,
300 undos: &'a UndoMap,
301 since: time::Global,
302 delta: isize,
303}
304
305#[derive(Clone, Debug, Default, Eq, PartialEq)]
306pub struct Edit {
307 pub old_range: Range<usize>,
308 pub new_range: Range<usize>,
309 pub old_lines: Point,
310}
311
312impl Edit {
313 pub fn delta(&self) -> isize {
314 (self.new_range.end - self.new_range.start) as isize
315 - (self.old_range.end - self.old_range.start) as isize
316 }
317
318 pub fn old_extent(&self) -> usize {
319 self.old_range.end - self.old_range.start
320 }
321}
322
323struct Diff {
324 base_version: time::Global,
325 new_text: Arc<str>,
326 changes: Vec<(ChangeTag, usize)>,
327}
328
329#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
330struct InsertionTimestamp {
331 replica_id: ReplicaId,
332 local: time::Seq,
333 lamport: time::Seq,
334}
335
336impl InsertionTimestamp {
337 fn local(&self) -> time::Local {
338 time::Local {
339 replica_id: self.replica_id,
340 value: self.local,
341 }
342 }
343
344 fn lamport(&self) -> time::Lamport {
345 time::Lamport {
346 replica_id: self.replica_id,
347 value: self.lamport,
348 }
349 }
350}
351
352#[derive(Eq, PartialEq, Clone, Debug)]
353struct Fragment {
354 timestamp: InsertionTimestamp,
355 len: usize,
356 visible: bool,
357 deletions: HashSet<time::Local>,
358 max_undos: time::Global,
359}
360
361#[derive(Eq, PartialEq, Clone, Debug)]
362pub struct FragmentSummary {
363 text: FragmentTextSummary,
364 max_version: time::Global,
365 min_insertion_version: time::Global,
366 max_insertion_version: time::Global,
367}
368
369#[derive(Copy, Default, Clone, Debug, PartialEq, Eq)]
370struct FragmentTextSummary {
371 visible: usize,
372 deleted: usize,
373}
374
375impl<'a> sum_tree::Dimension<'a, FragmentSummary> for FragmentTextSummary {
376 fn add_summary(&mut self, summary: &'a FragmentSummary, _: &Option<time::Global>) {
377 self.visible += summary.text.visible;
378 self.deleted += summary.text.deleted;
379 }
380}
381
382#[derive(Clone, Debug, Eq, PartialEq)]
383pub enum Operation {
384 Edit(EditOperation),
385 Undo {
386 undo: UndoOperation,
387 lamport_timestamp: time::Lamport,
388 },
389 UpdateSelections {
390 set_id: SelectionSetId,
391 selections: Option<Arc<[Selection]>>,
392 lamport_timestamp: time::Lamport,
393 },
394}
395
396#[derive(Clone, Debug, Eq, PartialEq)]
397pub struct EditOperation {
398 timestamp: InsertionTimestamp,
399 version: time::Global,
400 ranges: Vec<Range<usize>>,
401 new_text: Option<String>,
402}
403
404#[derive(Copy, Clone, Debug, Eq, PartialEq)]
405pub struct UndoOperation {
406 id: time::Local,
407 edit_id: time::Local,
408 count: u32,
409}
410
411impl Buffer {
412 pub fn new<T: Into<Arc<str>>>(
413 replica_id: ReplicaId,
414 base_text: T,
415 cx: &mut ModelContext<Self>,
416 ) -> Self {
417 Self::build(replica_id, History::new(base_text.into()), None, None, cx)
418 }
419
420 pub fn from_history(
421 replica_id: ReplicaId,
422 history: History,
423 file: Option<FileHandle>,
424 language: Option<Arc<Language>>,
425 cx: &mut ModelContext<Self>,
426 ) -> Self {
427 Self::build(replica_id, history, file, language, cx)
428 }
429
430 fn build(
431 replica_id: ReplicaId,
432 history: History,
433 file: Option<FileHandle>,
434 language: Option<Arc<Language>>,
435 cx: &mut ModelContext<Self>,
436 ) -> Self {
437 let saved_mtime;
438 if let Some(file) = file.as_ref() {
439 saved_mtime = file.mtime();
440 file.observe_from_model(cx, |this, file, cx| {
441 let version = this.version.clone();
442 if this.version == this.saved_version {
443 if file.is_deleted() {
444 cx.emit(Event::Dirtied);
445 } else {
446 cx.spawn(|handle, mut cx| async move {
447 let (current_version, history) = handle.read_with(&cx, |this, cx| {
448 (this.version.clone(), file.load_history(cx.as_ref()))
449 });
450 if let (Ok(history), true) = (history.await, current_version == version)
451 {
452 let diff = handle
453 .read_with(&cx, |this, cx| this.diff(history.base_text, cx))
454 .await;
455 handle.update(&mut cx, |this, cx| {
456 if let Some(_ops) = this.set_text_via_diff(diff, cx) {
457 this.saved_version = this.version.clone();
458 this.saved_mtime = file.mtime();
459 cx.emit(Event::Reloaded);
460 }
461 });
462 }
463 })
464 .detach();
465 }
466 }
467 cx.emit(Event::FileHandleChanged);
468 });
469 } else {
470 saved_mtime = UNIX_EPOCH;
471 }
472
473 let mut fragments = SumTree::new();
474
475 let visible_text = Rope::from(history.base_text.as_ref());
476 if visible_text.len() > 0 {
477 fragments.push(
478 Fragment {
479 timestamp: Default::default(),
480 len: visible_text.len(),
481 visible: true,
482 deletions: Default::default(),
483 max_undos: Default::default(),
484 },
485 &None,
486 );
487 }
488
489 let mut result = Self {
490 visible_text,
491 deleted_text: Rope::new(),
492 fragments,
493 version: time::Global::new(),
494 saved_version: time::Global::new(),
495 last_edit: time::Local::default(),
496 undo_map: Default::default(),
497 history,
498 file,
499 syntax_tree: Mutex::new(None),
500 is_parsing: false,
501 language,
502 saved_mtime,
503 selections: HashMap::default(),
504 selections_last_update: 0,
505 deferred_ops: OperationQueue::new(),
506 deferred_replicas: HashSet::default(),
507 replica_id,
508 local_clock: time::Local::new(replica_id),
509 lamport_clock: time::Lamport::new(replica_id),
510 };
511 result.reparse(cx);
512 result
513 }
514
515 pub fn snapshot(&self) -> Snapshot {
516 Snapshot {
517 text: self.visible_text.clone(),
518 tree: self.syntax_tree(),
519 language: self.language.clone(),
520 query_cursor: QueryCursorHandle::new(),
521 }
522 }
523
524 pub fn file(&self) -> Option<&FileHandle> {
525 self.file.as_ref()
526 }
527
528 pub fn save(
529 &mut self,
530 new_file: Option<FileHandle>,
531 cx: &mut ModelContext<Self>,
532 ) -> Task<Result<()>> {
533 let text = self.visible_text.clone();
534 let version = self.version.clone();
535 let file = self.file.clone();
536
537 cx.spawn(|handle, mut cx| async move {
538 if let Some(file) = new_file.as_ref().or(file.as_ref()) {
539 let result = cx.read(|cx| file.save(text, cx.as_ref())).await;
540 if result.is_ok() {
541 handle.update(&mut cx, |me, cx| me.did_save(version, new_file, cx));
542 }
543 result
544 } else {
545 Ok(())
546 }
547 })
548 }
549
550 fn did_save(
551 &mut self,
552 version: time::Global,
553 file: Option<FileHandle>,
554 cx: &mut ModelContext<Buffer>,
555 ) {
556 if file.is_some() {
557 self.file = file;
558 }
559 if let Some(file) = &self.file {
560 self.saved_mtime = file.mtime();
561 }
562 self.saved_version = version;
563 cx.emit(Event::Saved);
564 }
565
566 pub fn syntax_tree(&self) -> Option<Tree> {
567 if let Some(syntax_tree) = self.syntax_tree.lock().as_mut() {
568 let mut edited = false;
569 let mut delta = 0_isize;
570 for Edit {
571 old_range,
572 new_range,
573 old_lines,
574 } in self.edits_since(syntax_tree.version.clone())
575 {
576 let start_offset = (old_range.start as isize + delta) as usize;
577 let start_point = self.visible_text.to_point(start_offset);
578 let old_bytes = old_range.end - old_range.start;
579 let new_bytes = new_range.end - new_range.start;
580 syntax_tree.tree.edit(&InputEdit {
581 start_byte: start_offset,
582 old_end_byte: start_offset + old_bytes,
583 new_end_byte: start_offset + new_bytes,
584 start_position: start_point.into(),
585 old_end_position: (start_point + old_lines).into(),
586 new_end_position: self.visible_text.to_point(start_offset + new_bytes).into(),
587 });
588 delta += new_bytes as isize - old_bytes as isize;
589 edited = true;
590 }
591 syntax_tree.parsed &= !edited;
592 syntax_tree.version = self.version();
593 Some(syntax_tree.tree.clone())
594 } else {
595 None
596 }
597 }
598
599 pub fn is_parsing(&self) -> bool {
600 self.is_parsing
601 }
602
603 fn should_reparse(&self) -> bool {
604 if let Some(syntax_tree) = self.syntax_tree.lock().as_ref() {
605 !syntax_tree.parsed || syntax_tree.version != self.version
606 } else {
607 self.language.is_some()
608 }
609 }
610
611 fn reparse(&mut self, cx: &mut ModelContext<Self>) {
612 // Avoid spawning a new parsing task if the buffer is already being reparsed
613 // due to an earlier edit.
614 if self.is_parsing {
615 return;
616 }
617
618 if let Some(language) = self.language.clone() {
619 self.is_parsing = true;
620 cx.spawn(|handle, mut cx| async move {
621 while handle.read_with(&cx, |this, _| this.should_reparse()) {
622 // The parse tree is out of date, so grab the syntax tree to synchronously
623 // splice all the edits that have happened since the last parse.
624 let new_tree = handle.update(&mut cx, |this, _| this.syntax_tree());
625 let (new_text, new_version) = handle
626 .read_with(&cx, |this, _| (this.visible_text.clone(), this.version()));
627
628 // Parse the current text in a background thread.
629 let new_tree = cx
630 .background_executor()
631 .spawn({
632 let language = language.clone();
633 async move { Self::parse_text(&new_text, new_tree, &language) }
634 })
635 .await;
636
637 handle.update(&mut cx, |this, cx| {
638 *this.syntax_tree.lock() = Some(SyntaxTree {
639 tree: new_tree,
640 parsed: true,
641 version: new_version,
642 });
643 cx.emit(Event::Reparsed);
644 cx.notify();
645 });
646 }
647 handle.update(&mut cx, |this, _| this.is_parsing = false);
648 })
649 .detach();
650 }
651 }
652
653 fn parse_text(text: &Rope, old_tree: Option<Tree>, language: &Language) -> Tree {
654 PARSER.with(|parser| {
655 let mut parser = parser.borrow_mut();
656 parser
657 .set_language(language.grammar)
658 .expect("incompatible grammar");
659 let mut chunks = text.chunks_in_range(0..text.len());
660 let tree = parser
661 .parse_with(
662 &mut move |offset, _| {
663 chunks.seek(offset);
664 chunks.next().unwrap_or("").as_bytes()
665 },
666 old_tree.as_ref(),
667 )
668 .unwrap();
669 tree
670 })
671 }
672
673 pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
674 if let Some(tree) = self.syntax_tree() {
675 let root = tree.root_node();
676 let range = range.start.to_offset(self)..range.end.to_offset(self);
677 let mut node = root.descendant_for_byte_range(range.start, range.end);
678 while node.map_or(false, |n| n.byte_range() == range) {
679 node = node.unwrap().parent();
680 }
681 node.map(|n| n.byte_range())
682 } else {
683 None
684 }
685 }
686
687 pub fn enclosing_bracket_ranges<T: ToOffset>(
688 &self,
689 range: Range<T>,
690 ) -> Option<(Range<usize>, Range<usize>)> {
691 let (lang, tree) = self.language.as_ref().zip(self.syntax_tree())?;
692 let open_capture_ix = lang.brackets_query.capture_index_for_name("open")?;
693 let close_capture_ix = lang.brackets_query.capture_index_for_name("close")?;
694
695 // Find bracket pairs that *inclusively* contain the given range.
696 let range = range.start.to_offset(self).saturating_sub(1)..range.end.to_offset(self) + 1;
697 let mut cursor = QueryCursorHandle::new();
698 let matches = cursor.set_byte_range(range).matches(
699 &lang.brackets_query,
700 tree.root_node(),
701 TextProvider(&self.visible_text),
702 );
703
704 // Get the ranges of the innermost pair of brackets.
705 matches
706 .filter_map(|mat| {
707 let open = mat.nodes_for_capture_index(open_capture_ix).next()?;
708 let close = mat.nodes_for_capture_index(close_capture_ix).next()?;
709 Some((open.byte_range(), close.byte_range()))
710 })
711 .min_by_key(|(open_range, close_range)| close_range.end - open_range.start)
712 }
713
714 fn diff(&self, new_text: Arc<str>, cx: &AppContext) -> Task<Diff> {
715 // TODO: it would be nice to not allocate here.
716 let old_text = self.text();
717 let base_version = self.version();
718 cx.background_executor().spawn(async move {
719 let changes = TextDiff::from_lines(old_text.as_str(), new_text.as_ref())
720 .iter_all_changes()
721 .map(|c| (c.tag(), c.value().len()))
722 .collect::<Vec<_>>();
723 Diff {
724 base_version,
725 new_text,
726 changes,
727 }
728 })
729 }
730
731 fn set_text_via_diff(
732 &mut self,
733 diff: Diff,
734 cx: &mut ModelContext<Self>,
735 ) -> Option<Vec<Operation>> {
736 if self.version == diff.base_version {
737 self.start_transaction(None).unwrap();
738 let mut operations = Vec::new();
739 let mut offset = 0;
740 for (tag, len) in diff.changes {
741 let range = offset..(offset + len);
742 match tag {
743 ChangeTag::Equal => offset += len,
744 ChangeTag::Delete => {
745 operations.push(self.edit(Some(range), "", Some(cx)).unwrap())
746 }
747 ChangeTag::Insert => {
748 operations.push(
749 self.edit(Some(offset..offset), &diff.new_text[range], Some(cx))
750 .unwrap(),
751 );
752 offset += len;
753 }
754 }
755 }
756 self.end_transaction(None, Some(cx)).unwrap();
757 Some(operations)
758 } else {
759 None
760 }
761 }
762
763 pub fn is_dirty(&self) -> bool {
764 self.version > self.saved_version || self.file.as_ref().map_or(false, |f| f.is_deleted())
765 }
766
767 pub fn has_conflict(&self) -> bool {
768 self.version > self.saved_version
769 && self
770 .file
771 .as_ref()
772 .map_or(false, |f| f.mtime() > self.saved_mtime)
773 }
774
775 pub fn version(&self) -> time::Global {
776 self.version.clone()
777 }
778
779 pub fn text_summary(&self) -> TextSummary {
780 self.visible_text.summary()
781 }
782
783 pub fn text_summary_for_range(&self, range: Range<usize>) -> TextSummary {
784 self.visible_text.cursor(range.start).summary(range.end)
785 }
786
787 pub fn len(&self) -> usize {
788 self.fragments.extent::<usize>(&None)
789 }
790
791 pub fn line_len(&self, row: u32) -> u32 {
792 let row_start_offset = Point::new(row, 0).to_offset(self);
793 let row_end_offset = if row >= self.max_point().row {
794 self.len()
795 } else {
796 Point::new(row + 1, 0).to_offset(self) - 1
797 };
798 (row_end_offset - row_start_offset) as u32
799 }
800
801 pub fn max_point(&self) -> Point {
802 self.visible_text.max_point()
803 }
804
805 pub fn row_count(&self) -> u32 {
806 self.max_point().row + 1
807 }
808
809 pub fn text(&self) -> String {
810 self.text_for_range(0..self.len()).collect()
811 }
812
813 pub fn text_for_range<'a, T: ToOffset>(&'a self, range: Range<T>) -> Chunks<'a> {
814 let start = range.start.to_offset(self);
815 let end = range.end.to_offset(self);
816 self.visible_text.chunks_in_range(start..end)
817 }
818
819 pub fn chars(&self) -> impl Iterator<Item = char> + '_ {
820 self.chars_at(0)
821 }
822
823 pub fn chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + '_ {
824 let offset = position.to_offset(self);
825 self.visible_text.chars_at(offset)
826 }
827
828 pub fn selections_changed_since(&self, since: SelectionsVersion) -> bool {
829 self.selections_last_update != since
830 }
831
832 pub fn edits_since<'a>(&'a self, since: time::Global) -> impl 'a + Iterator<Item = Edit> {
833 let since_2 = since.clone();
834 let cursor = self.fragments.filter(
835 move |summary| summary.max_version.changed_since(&since_2),
836 &None,
837 );
838
839 Edits {
840 deleted_text: &self.deleted_text,
841 cursor,
842 undos: &self.undo_map,
843 since,
844 delta: 0,
845 }
846 }
847
848 pub fn deferred_ops_len(&self) -> usize {
849 self.deferred_ops.len()
850 }
851
852 pub fn start_transaction(&mut self, set_id: Option<SelectionSetId>) -> Result<()> {
853 self.start_transaction_at(set_id, Instant::now())
854 }
855
856 fn start_transaction_at(&mut self, set_id: Option<SelectionSetId>, now: Instant) -> Result<()> {
857 let selections = if let Some(set_id) = set_id {
858 let selections = self
859 .selections
860 .get(&set_id)
861 .ok_or_else(|| anyhow!("invalid selection set {:?}", set_id))?;
862 Some((set_id, selections.clone()))
863 } else {
864 None
865 };
866 self.history
867 .start_transaction(self.version.clone(), self.is_dirty(), selections, now);
868 Ok(())
869 }
870
871 pub fn end_transaction(
872 &mut self,
873 set_id: Option<SelectionSetId>,
874 cx: Option<&mut ModelContext<Self>>,
875 ) -> Result<()> {
876 self.end_transaction_at(set_id, Instant::now(), cx)
877 }
878
879 fn end_transaction_at(
880 &mut self,
881 set_id: Option<SelectionSetId>,
882 now: Instant,
883 cx: Option<&mut ModelContext<Self>>,
884 ) -> Result<()> {
885 let selections = if let Some(set_id) = set_id {
886 let selections = self
887 .selections
888 .get(&set_id)
889 .ok_or_else(|| anyhow!("invalid selection set {:?}", set_id))?;
890 Some((set_id, selections.clone()))
891 } else {
892 None
893 };
894
895 if let Some(transaction) = self.history.end_transaction(selections, now) {
896 let since = transaction.start.clone();
897 let was_dirty = transaction.buffer_was_dirty;
898 self.history.group();
899
900 if let Some(cx) = cx {
901 cx.notify();
902
903 if self.edits_since(since).next().is_some() {
904 self.did_edit(was_dirty, cx);
905 self.reparse(cx);
906 }
907 }
908 }
909
910 Ok(())
911 }
912
913 pub fn edit<I, S, T>(
914 &mut self,
915 ranges_iter: I,
916 new_text: T,
917 cx: Option<&mut ModelContext<Self>>,
918 ) -> Option<Operation>
919 where
920 I: IntoIterator<Item = Range<S>>,
921 S: ToOffset,
922 T: Into<String>,
923 {
924 let new_text = new_text.into();
925 let new_text = if new_text.len() > 0 {
926 Some(new_text)
927 } else {
928 None
929 };
930 let has_new_text = new_text.is_some();
931
932 // Skip invalid ranges and coalesce contiguous ones.
933 let mut ranges: Vec<Range<usize>> = Vec::new();
934 for range in ranges_iter {
935 let range = range.start.to_offset(self)..range.end.to_offset(self);
936 if has_new_text || !range.is_empty() {
937 if let Some(prev_range) = ranges.last_mut() {
938 if prev_range.end >= range.start {
939 prev_range.end = cmp::max(prev_range.end, range.end);
940 } else {
941 ranges.push(range);
942 }
943 } else {
944 ranges.push(range);
945 }
946 }
947 }
948
949 if ranges.is_empty() {
950 None
951 } else {
952 self.start_transaction_at(None, Instant::now()).unwrap();
953 let timestamp = InsertionTimestamp {
954 replica_id: self.replica_id,
955 local: self.local_clock.tick().value,
956 lamport: self.lamport_clock.tick().value,
957 };
958 let edit = self.apply_local_edit(&ranges, new_text, timestamp);
959
960 self.history.push(edit.clone());
961 self.history.push_undo(edit.timestamp.local());
962 self.last_edit = edit.timestamp.local();
963 self.version.observe(edit.timestamp.local());
964
965 self.end_transaction_at(None, Instant::now(), cx).unwrap();
966
967 Some(Operation::Edit(edit))
968 }
969 }
970
971 fn did_edit(&self, was_dirty: bool, cx: &mut ModelContext<Self>) {
972 cx.emit(Event::Edited);
973 if !was_dirty {
974 cx.emit(Event::Dirtied);
975 }
976 }
977
978 pub fn add_selection_set(
979 &mut self,
980 selections: impl Into<Arc<[Selection]>>,
981 cx: Option<&mut ModelContext<Self>>,
982 ) -> (SelectionSetId, Operation) {
983 let selections = selections.into();
984 let lamport_timestamp = self.lamport_clock.tick();
985 self.selections
986 .insert(lamport_timestamp, Arc::clone(&selections));
987 self.selections_last_update += 1;
988
989 if let Some(cx) = cx {
990 cx.notify();
991 }
992
993 (
994 lamport_timestamp,
995 Operation::UpdateSelections {
996 set_id: lamport_timestamp,
997 selections: Some(selections),
998 lamport_timestamp,
999 },
1000 )
1001 }
1002
1003 pub fn update_selection_set(
1004 &mut self,
1005 set_id: SelectionSetId,
1006 selections: impl Into<Arc<[Selection]>>,
1007 cx: Option<&mut ModelContext<Self>>,
1008 ) -> Result<Operation> {
1009 let selections = selections.into();
1010 self.selections.insert(set_id, selections.clone());
1011
1012 let lamport_timestamp = self.lamport_clock.tick();
1013 self.selections_last_update += 1;
1014
1015 if let Some(cx) = cx {
1016 cx.notify();
1017 }
1018
1019 Ok(Operation::UpdateSelections {
1020 set_id,
1021 selections: Some(selections),
1022 lamport_timestamp,
1023 })
1024 }
1025
1026 pub fn remove_selection_set(
1027 &mut self,
1028 set_id: SelectionSetId,
1029 cx: Option<&mut ModelContext<Self>>,
1030 ) -> Result<Operation> {
1031 self.selections
1032 .remove(&set_id)
1033 .ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))?;
1034 let lamport_timestamp = self.lamport_clock.tick();
1035 self.selections_last_update += 1;
1036
1037 if let Some(cx) = cx {
1038 cx.notify();
1039 }
1040
1041 Ok(Operation::UpdateSelections {
1042 set_id,
1043 selections: None,
1044 lamport_timestamp,
1045 })
1046 }
1047
1048 pub fn selections(&self, set_id: SelectionSetId) -> Result<&[Selection]> {
1049 self.selections
1050 .get(&set_id)
1051 .map(|s| s.as_ref())
1052 .ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))
1053 }
1054
1055 pub fn apply_ops<I: IntoIterator<Item = Operation>>(
1056 &mut self,
1057 ops: I,
1058 cx: Option<&mut ModelContext<Self>>,
1059 ) -> Result<()> {
1060 let was_dirty = self.is_dirty();
1061 let old_version = self.version.clone();
1062
1063 let mut deferred_ops = Vec::new();
1064 for op in ops {
1065 if self.can_apply_op(&op) {
1066 self.apply_op(op)?;
1067 } else {
1068 self.deferred_replicas.insert(op.replica_id());
1069 deferred_ops.push(op);
1070 }
1071 }
1072 self.deferred_ops.insert(deferred_ops);
1073 self.flush_deferred_ops()?;
1074
1075 if let Some(cx) = cx {
1076 cx.notify();
1077 if self.edits_since(old_version).next().is_some() {
1078 self.did_edit(was_dirty, cx);
1079 self.reparse(cx);
1080 }
1081 }
1082
1083 Ok(())
1084 }
1085
1086 fn apply_op(&mut self, op: Operation) -> Result<()> {
1087 match op {
1088 Operation::Edit(edit) => {
1089 if !self.version.observed(edit.timestamp.local()) {
1090 self.apply_remote_edit(
1091 &edit.version,
1092 &edit.ranges,
1093 edit.new_text.as_deref(),
1094 edit.timestamp,
1095 );
1096 self.version.observe(edit.timestamp.local());
1097 self.history.push(edit);
1098 }
1099 }
1100 Operation::Undo {
1101 undo,
1102 lamport_timestamp,
1103 } => {
1104 if !self.version.observed(undo.id) {
1105 self.apply_undo(undo)?;
1106 self.version.observe(undo.id);
1107 self.lamport_clock.observe(lamport_timestamp);
1108 }
1109 }
1110 Operation::UpdateSelections {
1111 set_id,
1112 selections,
1113 lamport_timestamp,
1114 } => {
1115 if let Some(selections) = selections {
1116 self.selections.insert(set_id, selections);
1117 } else {
1118 self.selections.remove(&set_id);
1119 }
1120 self.lamport_clock.observe(lamport_timestamp);
1121 self.selections_last_update += 1;
1122 }
1123 }
1124 Ok(())
1125 }
1126
1127 fn apply_remote_edit(
1128 &mut self,
1129 version: &time::Global,
1130 ranges: &[Range<usize>],
1131 new_text: Option<&str>,
1132 timestamp: InsertionTimestamp,
1133 ) {
1134 if ranges.is_empty() {
1135 return;
1136 }
1137
1138 let cx = Some(version.clone());
1139 let mut new_ropes =
1140 RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
1141 let mut old_fragments = self.fragments.cursor::<VersionedOffset, VersionedOffset>();
1142 let mut new_fragments =
1143 old_fragments.slice(&VersionedOffset::Offset(ranges[0].start), Bias::Left, &cx);
1144 new_ropes.push_tree(new_fragments.summary().text);
1145
1146 let mut fragment_start = old_fragments.start().offset();
1147 for range in ranges {
1148 let fragment_end = old_fragments.end(&cx).offset();
1149
1150 // If the current fragment ends before this range, then jump ahead to the first fragment
1151 // that extends past the start of this range, reusing any intervening fragments.
1152 if fragment_end < range.start {
1153 // If the current fragment has been partially consumed, then consume the rest of it
1154 // and advance to the next fragment before slicing.
1155 if fragment_start > old_fragments.start().offset() {
1156 if fragment_end > fragment_start {
1157 let mut suffix = old_fragments.item().unwrap().clone();
1158 suffix.len = fragment_end - fragment_start;
1159 new_ropes.push_fragment(&suffix, suffix.visible);
1160 new_fragments.push(suffix, &None);
1161 }
1162 old_fragments.next(&cx);
1163 }
1164
1165 let slice =
1166 old_fragments.slice(&VersionedOffset::Offset(range.start), Bias::Left, &cx);
1167 new_ropes.push_tree(slice.summary().text);
1168 new_fragments.push_tree(slice, &None);
1169 fragment_start = old_fragments.start().offset();
1170 }
1171
1172 // If we are at the end of a non-concurrent fragment, advance to the next one.
1173 let fragment_end = old_fragments.end(&cx).offset();
1174 if fragment_end == range.start && fragment_end > fragment_start {
1175 let mut fragment = old_fragments.item().unwrap().clone();
1176 fragment.len = fragment_end - fragment_start;
1177 new_ropes.push_fragment(&fragment, fragment.visible);
1178 new_fragments.push(fragment, &None);
1179 old_fragments.next(&cx);
1180 fragment_start = old_fragments.start().offset();
1181 }
1182
1183 // Skip over insertions that are concurrent to this edit, but have a lower lamport
1184 // timestamp.
1185 while let Some(fragment) = old_fragments.item() {
1186 if fragment_start == range.start
1187 && fragment.timestamp.lamport() > timestamp.lamport()
1188 {
1189 new_ropes.push_fragment(fragment, fragment.visible);
1190 new_fragments.push(fragment.clone(), &None);
1191 old_fragments.next(&cx);
1192 debug_assert_eq!(fragment_start, range.start);
1193 } else {
1194 break;
1195 }
1196 }
1197 debug_assert!(fragment_start <= range.start);
1198
1199 // Preserve any portion of the current fragment that precedes this range.
1200 if fragment_start < range.start {
1201 let mut prefix = old_fragments.item().unwrap().clone();
1202 prefix.len = range.start - fragment_start;
1203 fragment_start = range.start;
1204 new_ropes.push_fragment(&prefix, prefix.visible);
1205 new_fragments.push(prefix, &None);
1206 }
1207
1208 // Insert the new text before any existing fragments within the range.
1209 if let Some(new_text) = new_text {
1210 new_ropes.push_str(new_text);
1211 new_fragments.push(
1212 Fragment {
1213 timestamp,
1214 len: new_text.len(),
1215 deletions: Default::default(),
1216 max_undos: Default::default(),
1217 visible: true,
1218 },
1219 &None,
1220 );
1221 }
1222
1223 // Advance through every fragment that intersects this range, marking the intersecting
1224 // portions as deleted.
1225 while fragment_start < range.end {
1226 let fragment = old_fragments.item().unwrap();
1227 let fragment_end = old_fragments.end(&cx).offset();
1228 let mut intersection = fragment.clone();
1229 let intersection_end = cmp::min(range.end, fragment_end);
1230 if fragment.was_visible(version, &self.undo_map) {
1231 intersection.len = intersection_end - fragment_start;
1232 intersection.deletions.insert(timestamp.local());
1233 intersection.visible = false;
1234 }
1235 if intersection.len > 0 {
1236 new_ropes.push_fragment(&intersection, fragment.visible);
1237 new_fragments.push(intersection, &None);
1238 fragment_start = intersection_end;
1239 }
1240 if fragment_end <= range.end {
1241 old_fragments.next(&cx);
1242 }
1243 }
1244 }
1245
1246 // If the current fragment has been partially consumed, then consume the rest of it
1247 // and advance to the next fragment before slicing.
1248 if fragment_start > old_fragments.start().offset() {
1249 let fragment_end = old_fragments.end(&cx).offset();
1250 if fragment_end > fragment_start {
1251 let mut suffix = old_fragments.item().unwrap().clone();
1252 suffix.len = fragment_end - fragment_start;
1253 new_ropes.push_fragment(&suffix, suffix.visible);
1254 new_fragments.push(suffix, &None);
1255 }
1256 old_fragments.next(&cx);
1257 }
1258
1259 let suffix = old_fragments.suffix(&cx);
1260 new_ropes.push_tree(suffix.summary().text);
1261 new_fragments.push_tree(suffix, &None);
1262 let (visible_text, deleted_text) = new_ropes.finish();
1263 drop(old_fragments);
1264
1265 self.fragments = new_fragments;
1266 self.visible_text = visible_text;
1267 self.deleted_text = deleted_text;
1268 self.local_clock.observe(timestamp.local());
1269 self.lamport_clock.observe(timestamp.lamport());
1270 }
1271
1272 pub fn undo(&mut self, mut cx: Option<&mut ModelContext<Self>>) -> Vec<Operation> {
1273 let was_dirty = self.is_dirty();
1274 let old_version = self.version.clone();
1275
1276 let mut ops = Vec::new();
1277 if let Some(transaction) = self.history.pop_undo() {
1278 let selections = transaction.selections_before.clone();
1279 for edit_id in transaction.edits.clone() {
1280 ops.push(self.undo_or_redo(edit_id).unwrap());
1281 }
1282
1283 if let Some((set_id, selections)) = selections {
1284 let _ = self.update_selection_set(set_id, selections, cx.as_deref_mut());
1285 }
1286 }
1287
1288 if let Some(cx) = cx {
1289 cx.notify();
1290 if self.edits_since(old_version).next().is_some() {
1291 self.did_edit(was_dirty, cx);
1292 self.reparse(cx);
1293 }
1294 }
1295
1296 ops
1297 }
1298
1299 pub fn redo(&mut self, mut cx: Option<&mut ModelContext<Self>>) -> Vec<Operation> {
1300 let was_dirty = self.is_dirty();
1301 let old_version = self.version.clone();
1302
1303 let mut ops = Vec::new();
1304 if let Some(transaction) = self.history.pop_redo() {
1305 let selections = transaction.selections_after.clone();
1306 for edit_id in transaction.edits.clone() {
1307 ops.push(self.undo_or_redo(edit_id).unwrap());
1308 }
1309
1310 if let Some((set_id, selections)) = selections {
1311 let _ = self.update_selection_set(set_id, selections, cx.as_deref_mut());
1312 }
1313 }
1314
1315 if let Some(cx) = cx {
1316 cx.notify();
1317 if self.edits_since(old_version).next().is_some() {
1318 self.did_edit(was_dirty, cx);
1319 self.reparse(cx);
1320 }
1321 }
1322
1323 ops
1324 }
1325
1326 fn undo_or_redo(&mut self, edit_id: time::Local) -> Result<Operation> {
1327 let undo = UndoOperation {
1328 id: self.local_clock.tick(),
1329 edit_id,
1330 count: self.undo_map.undo_count(edit_id) + 1,
1331 };
1332 self.apply_undo(undo)?;
1333 self.version.observe(undo.id);
1334
1335 Ok(Operation::Undo {
1336 undo,
1337 lamport_timestamp: self.lamport_clock.tick(),
1338 })
1339 }
1340
1341 fn apply_undo(&mut self, undo: UndoOperation) -> Result<()> {
1342 self.undo_map.insert(undo);
1343
1344 let edit = &self.history.ops[&undo.edit_id];
1345 let mut cx = edit.version.clone();
1346 cx.observe(undo.edit_id);
1347 let cx = Some(cx);
1348
1349 let mut old_fragments = self.fragments.cursor::<VersionedOffset, VersionedOffset>();
1350 let mut new_fragments = old_fragments.slice(
1351 &VersionedOffset::Offset(edit.ranges[0].start),
1352 Bias::Right,
1353 &cx,
1354 );
1355 let mut new_ropes =
1356 RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
1357 new_ropes.push_tree(new_fragments.summary().text);
1358
1359 let insertion_len = edit.new_text.as_ref().map_or(0, |i| i.len());
1360 for (ix, range) in edit.ranges.iter().enumerate() {
1361 let delta = ix * insertion_len;
1362 let mut end_offset = old_fragments.end(&cx).offset();
1363
1364 if end_offset < range.start + delta {
1365 let preceding_fragments = old_fragments.slice(
1366 &VersionedOffset::Offset(range.start + delta),
1367 Bias::Right,
1368 &cx,
1369 );
1370 new_ropes.push_tree(preceding_fragments.summary().text);
1371 new_fragments.push_tree(preceding_fragments, &None);
1372 }
1373
1374 while end_offset <= delta + range.end + insertion_len {
1375 if let Some(fragment) = old_fragments.item() {
1376 let mut fragment = fragment.clone();
1377 let fragment_was_visible = fragment.visible;
1378
1379 if fragment.was_visible(&edit.version, &self.undo_map)
1380 || fragment.timestamp.local() == edit.timestamp.local()
1381 {
1382 fragment.visible = fragment.is_visible(&self.undo_map);
1383 fragment.max_undos.observe(undo.id);
1384 }
1385 new_ropes.push_fragment(&fragment, fragment_was_visible);
1386 new_fragments.push(fragment, &None);
1387
1388 old_fragments.next(&cx);
1389 if end_offset == old_fragments.end(&cx).offset() {
1390 let unseen_fragments = old_fragments.slice(
1391 &VersionedOffset::Offset(end_offset),
1392 Bias::Right,
1393 &cx,
1394 );
1395 new_ropes.push_tree(unseen_fragments.summary().text);
1396 new_fragments.push_tree(unseen_fragments, &None);
1397 }
1398 end_offset = old_fragments.end(&cx).offset();
1399 } else {
1400 break;
1401 }
1402 }
1403 }
1404
1405 let suffix = old_fragments.suffix(&cx);
1406 new_ropes.push_tree(suffix.summary().text);
1407 new_fragments.push_tree(suffix, &None);
1408
1409 drop(old_fragments);
1410 let (visible_text, deleted_text) = new_ropes.finish();
1411 self.fragments = new_fragments;
1412 self.visible_text = visible_text;
1413 self.deleted_text = deleted_text;
1414 Ok(())
1415 }
1416
1417 fn flush_deferred_ops(&mut self) -> Result<()> {
1418 self.deferred_replicas.clear();
1419 let mut deferred_ops = Vec::new();
1420 for op in self.deferred_ops.drain().cursor().cloned() {
1421 if self.can_apply_op(&op) {
1422 self.apply_op(op)?;
1423 } else {
1424 self.deferred_replicas.insert(op.replica_id());
1425 deferred_ops.push(op);
1426 }
1427 }
1428 self.deferred_ops.insert(deferred_ops);
1429 Ok(())
1430 }
1431
1432 fn can_apply_op(&self, op: &Operation) -> bool {
1433 if self.deferred_replicas.contains(&op.replica_id()) {
1434 false
1435 } else {
1436 match op {
1437 Operation::Edit(edit) => self.version >= edit.version,
1438 Operation::Undo { undo, .. } => self.version.observed(undo.edit_id),
1439 Operation::UpdateSelections { selections, .. } => {
1440 if let Some(selections) = selections {
1441 selections.iter().all(|selection| {
1442 let contains_start = match &selection.start {
1443 Anchor::Middle { version, .. } => self.version >= *version,
1444 _ => true,
1445 };
1446 let contains_end = match &selection.end {
1447 Anchor::Middle { version, .. } => self.version >= *version,
1448 _ => true,
1449 };
1450 contains_start && contains_end
1451 })
1452 } else {
1453 true
1454 }
1455 }
1456 }
1457 }
1458 }
1459
1460 fn apply_local_edit(
1461 &mut self,
1462 ranges: &[Range<usize>],
1463 new_text: Option<String>,
1464 timestamp: InsertionTimestamp,
1465 ) -> EditOperation {
1466 let mut edit = EditOperation {
1467 timestamp,
1468 version: self.version(),
1469 ranges: Vec::with_capacity(ranges.len()),
1470 new_text: None,
1471 };
1472
1473 let mut new_ropes =
1474 RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
1475 let mut old_fragments = self.fragments.cursor::<usize, FragmentTextSummary>();
1476 let mut new_fragments = old_fragments.slice(&ranges[0].start, Bias::Right, &None);
1477 new_ropes.push_tree(new_fragments.summary().text);
1478
1479 let mut fragment_start = old_fragments.start().visible;
1480 for range in ranges {
1481 let fragment_end = old_fragments.end(&None).visible;
1482
1483 // If the current fragment ends before this range, then jump ahead to the first fragment
1484 // that extends past the start of this range, reusing any intervening fragments.
1485 if fragment_end < range.start {
1486 // If the current fragment has been partially consumed, then consume the rest of it
1487 // and advance to the next fragment before slicing.
1488 if fragment_start > old_fragments.start().visible {
1489 if fragment_end > fragment_start {
1490 let mut suffix = old_fragments.item().unwrap().clone();
1491 suffix.len = fragment_end - fragment_start;
1492 new_ropes.push_fragment(&suffix, suffix.visible);
1493 new_fragments.push(suffix, &None);
1494 }
1495 old_fragments.next(&None);
1496 }
1497
1498 let slice = old_fragments.slice(&range.start, Bias::Right, &None);
1499 new_ropes.push_tree(slice.summary().text);
1500 new_fragments.push_tree(slice, &None);
1501 fragment_start = old_fragments.start().visible;
1502 }
1503
1504 let full_range_start = range.start + old_fragments.start().deleted;
1505
1506 // Preserve any portion of the current fragment that precedes this range.
1507 if fragment_start < range.start {
1508 let mut prefix = old_fragments.item().unwrap().clone();
1509 prefix.len = range.start - fragment_start;
1510 new_ropes.push_fragment(&prefix, prefix.visible);
1511 new_fragments.push(prefix, &None);
1512 fragment_start = range.start;
1513 }
1514
1515 // Insert the new text before any existing fragments within the range.
1516 if let Some(new_text) = new_text.as_deref() {
1517 new_ropes.push_str(new_text);
1518 new_fragments.push(
1519 Fragment {
1520 timestamp,
1521 len: new_text.len(),
1522 deletions: Default::default(),
1523 max_undos: Default::default(),
1524 visible: true,
1525 },
1526 &None,
1527 );
1528 }
1529
1530 // Advance through every fragment that intersects this range, marking the intersecting
1531 // portions as deleted.
1532 while fragment_start < range.end {
1533 let fragment = old_fragments.item().unwrap();
1534 let fragment_end = old_fragments.end(&None).visible;
1535 let mut intersection = fragment.clone();
1536 let intersection_end = cmp::min(range.end, fragment_end);
1537 if fragment.visible {
1538 intersection.len = intersection_end - fragment_start;
1539 intersection.deletions.insert(timestamp.local());
1540 intersection.visible = false;
1541 }
1542 if intersection.len > 0 {
1543 new_ropes.push_fragment(&intersection, fragment.visible);
1544 new_fragments.push(intersection, &None);
1545 fragment_start = intersection_end;
1546 }
1547 if fragment_end <= range.end {
1548 old_fragments.next(&None);
1549 }
1550 }
1551
1552 let full_range_end = range.end + old_fragments.start().deleted;
1553 edit.ranges.push(full_range_start..full_range_end);
1554 }
1555
1556 // If the current fragment has been partially consumed, then consume the rest of it
1557 // and advance to the next fragment before slicing.
1558 if fragment_start > old_fragments.start().visible {
1559 let fragment_end = old_fragments.end(&None).visible;
1560 if fragment_end > fragment_start {
1561 let mut suffix = old_fragments.item().unwrap().clone();
1562 suffix.len = fragment_end - fragment_start;
1563 new_ropes.push_fragment(&suffix, suffix.visible);
1564 new_fragments.push(suffix, &None);
1565 }
1566 old_fragments.next(&None);
1567 }
1568
1569 let suffix = old_fragments.suffix(&None);
1570 new_ropes.push_tree(suffix.summary().text);
1571 new_fragments.push_tree(suffix, &None);
1572 let (visible_text, deleted_text) = new_ropes.finish();
1573 drop(old_fragments);
1574
1575 self.fragments = new_fragments;
1576 self.visible_text = visible_text;
1577 self.deleted_text = deleted_text;
1578 edit.new_text = new_text;
1579 edit
1580 }
1581
1582 pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
1583 self.anchor_at(position, Bias::Left)
1584 }
1585
1586 pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
1587 self.anchor_at(position, Bias::Right)
1588 }
1589
1590 pub fn anchor_at<T: ToOffset>(&self, position: T, bias: Bias) -> Anchor {
1591 let offset = position.to_offset(self);
1592 let max_offset = self.len();
1593 assert!(offset <= max_offset, "offset is out of range");
1594
1595 if offset == 0 && bias == Bias::Left {
1596 Anchor::Start
1597 } else if offset == max_offset && bias == Bias::Right {
1598 Anchor::End
1599 } else {
1600 let mut cursor = self.fragments.cursor::<usize, FragmentTextSummary>();
1601 cursor.seek(&offset, bias, &None);
1602 Anchor::Middle {
1603 offset: offset + cursor.start().deleted,
1604 bias,
1605 version: self.version(),
1606 }
1607 }
1608 }
1609
1610 fn summary_for_anchor(&self, anchor: &Anchor) -> TextSummary {
1611 match anchor {
1612 Anchor::Start => TextSummary::default(),
1613 Anchor::End => self.text_summary(),
1614 Anchor::Middle {
1615 offset,
1616 bias,
1617 version,
1618 } => {
1619 let mut cursor = self
1620 .fragments
1621 .cursor::<VersionedOffset, (VersionedOffset, usize)>();
1622 cursor.seek(
1623 &VersionedOffset::Offset(*offset),
1624 *bias,
1625 &Some(version.clone()),
1626 );
1627 let fragment = cursor.item().unwrap();
1628 let overshoot = if fragment.visible {
1629 offset - cursor.start().0.offset()
1630 } else {
1631 0
1632 };
1633
1634 self.text_summary_for_range(0..cursor.start().1 + overshoot)
1635 }
1636 }
1637 }
1638
1639 fn full_offset_for_anchor(&self, anchor: &Anchor) -> usize {
1640 match anchor {
1641 Anchor::Start => 0,
1642 Anchor::End => {
1643 let summary = self.fragments.summary();
1644 summary.text.visible + summary.text.deleted
1645 }
1646 Anchor::Middle {
1647 offset,
1648 bias,
1649 version,
1650 } => {
1651 let mut cursor = self
1652 .fragments
1653 .cursor::<VersionedOffset, (VersionedOffset, FragmentTextSummary)>();
1654 cursor.seek(
1655 &VersionedOffset::Offset(*offset),
1656 *bias,
1657 &Some(version.clone()),
1658 );
1659 let overshoot = offset - cursor.start().0.offset();
1660 let summary = cursor.start().1;
1661 summary.visible + summary.deleted + overshoot
1662 }
1663 }
1664 }
1665
1666 pub fn point_for_offset(&self, offset: usize) -> Result<Point> {
1667 if offset <= self.len() {
1668 Ok(self.text_summary_for_range(0..offset).lines)
1669 } else {
1670 Err(anyhow!("offset out of bounds"))
1671 }
1672 }
1673
1674 pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
1675 self.visible_text.clip_point(point, bias)
1676 }
1677
1678 pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
1679 self.visible_text.clip_offset(offset, bias)
1680 }
1681}
1682
1683impl Clone for Buffer {
1684 fn clone(&self) -> Self {
1685 Self {
1686 fragments: self.fragments.clone(),
1687 visible_text: self.visible_text.clone(),
1688 deleted_text: self.deleted_text.clone(),
1689 version: self.version.clone(),
1690 saved_version: self.saved_version.clone(),
1691 saved_mtime: self.saved_mtime,
1692 last_edit: self.last_edit.clone(),
1693 undo_map: self.undo_map.clone(),
1694 history: self.history.clone(),
1695 selections: self.selections.clone(),
1696 selections_last_update: self.selections_last_update.clone(),
1697 deferred_ops: self.deferred_ops.clone(),
1698 file: self.file.clone(),
1699 language: self.language.clone(),
1700 syntax_tree: Mutex::new(self.syntax_tree.lock().clone()),
1701 is_parsing: false,
1702 deferred_replicas: self.deferred_replicas.clone(),
1703 replica_id: self.replica_id,
1704 local_clock: self.local_clock.clone(),
1705 lamport_clock: self.lamport_clock.clone(),
1706 }
1707 }
1708}
1709
1710pub struct Snapshot {
1711 text: Rope,
1712 tree: Option<Tree>,
1713 language: Option<Arc<Language>>,
1714 query_cursor: QueryCursorHandle,
1715}
1716
1717impl Snapshot {
1718 pub fn len(&self) -> usize {
1719 self.text.len()
1720 }
1721
1722 pub fn text(&self) -> Rope {
1723 self.text.clone()
1724 }
1725
1726 pub fn text_for_range(&self, range: Range<usize>) -> Chunks {
1727 self.text.chunks_in_range(range)
1728 }
1729
1730 pub fn highlighted_text_for_range(&mut self, range: Range<usize>) -> HighlightedChunks {
1731 let chunks = self.text.chunks_in_range(range.clone());
1732 if let Some((language, tree)) = self.language.as_ref().zip(self.tree.as_ref()) {
1733 let captures = self.query_cursor.set_byte_range(range.clone()).captures(
1734 &language.highlight_query,
1735 tree.root_node(),
1736 TextProvider(&self.text),
1737 );
1738
1739 HighlightedChunks {
1740 range,
1741 chunks,
1742 highlights: Some(Highlights {
1743 captures,
1744 next_capture: None,
1745 stack: Default::default(),
1746 theme_mapping: language.theme_mapping(),
1747 }),
1748 }
1749 } else {
1750 HighlightedChunks {
1751 range,
1752 chunks,
1753 highlights: None,
1754 }
1755 }
1756 }
1757
1758 pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
1759 self.text.clip_offset(offset, bias)
1760 }
1761
1762 pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
1763 self.text.clip_point(point, bias)
1764 }
1765
1766 pub fn to_offset(&self, point: Point) -> usize {
1767 self.text.to_offset(point)
1768 }
1769
1770 pub fn to_point(&self, offset: usize) -> Point {
1771 self.text.to_point(offset)
1772 }
1773}
1774
1775struct RopeBuilder<'a> {
1776 old_visible_cursor: rope::Cursor<'a>,
1777 old_deleted_cursor: rope::Cursor<'a>,
1778 new_visible: Rope,
1779 new_deleted: Rope,
1780}
1781
1782impl<'a> RopeBuilder<'a> {
1783 fn new(old_visible_cursor: rope::Cursor<'a>, old_deleted_cursor: rope::Cursor<'a>) -> Self {
1784 Self {
1785 old_visible_cursor,
1786 old_deleted_cursor,
1787 new_visible: Rope::new(),
1788 new_deleted: Rope::new(),
1789 }
1790 }
1791
1792 fn push_tree(&mut self, len: FragmentTextSummary) {
1793 self.push(len.visible, true, true);
1794 self.push(len.deleted, false, false);
1795 }
1796
1797 fn push_fragment(&mut self, fragment: &Fragment, was_visible: bool) {
1798 debug_assert!(fragment.len > 0);
1799 self.push(fragment.len, was_visible, fragment.visible)
1800 }
1801
1802 fn push(&mut self, len: usize, was_visible: bool, is_visible: bool) {
1803 let text = if was_visible {
1804 self.old_visible_cursor
1805 .slice(self.old_visible_cursor.offset() + len)
1806 } else {
1807 self.old_deleted_cursor
1808 .slice(self.old_deleted_cursor.offset() + len)
1809 };
1810 if is_visible {
1811 self.new_visible.append(text);
1812 } else {
1813 self.new_deleted.append(text);
1814 }
1815 }
1816
1817 fn push_str(&mut self, text: &str) {
1818 self.new_visible.push(text);
1819 }
1820
1821 fn finish(mut self) -> (Rope, Rope) {
1822 self.new_visible.append(self.old_visible_cursor.suffix());
1823 self.new_deleted.append(self.old_deleted_cursor.suffix());
1824 (self.new_visible, self.new_deleted)
1825 }
1826}
1827
1828#[derive(Clone, Debug, Eq, PartialEq)]
1829pub enum Event {
1830 Edited,
1831 Dirtied,
1832 Saved,
1833 FileHandleChanged,
1834 Reloaded,
1835 Reparsed,
1836}
1837
1838impl Entity for Buffer {
1839 type Event = Event;
1840}
1841
1842impl<'a, F: Fn(&FragmentSummary) -> bool> Iterator for Edits<'a, F> {
1843 type Item = Edit;
1844
1845 fn next(&mut self) -> Option<Self::Item> {
1846 let mut change: Option<Edit> = None;
1847
1848 while let Some(fragment) = self.cursor.item() {
1849 let new_offset = self.cursor.start().visible;
1850 let old_offset = (new_offset as isize - self.delta) as usize;
1851
1852 if !fragment.was_visible(&self.since, &self.undos) && fragment.visible {
1853 if let Some(ref mut change) = change {
1854 if change.new_range.end == new_offset {
1855 change.new_range.end += fragment.len;
1856 self.delta += fragment.len as isize;
1857 } else {
1858 break;
1859 }
1860 } else {
1861 change = Some(Edit {
1862 old_range: old_offset..old_offset,
1863 new_range: new_offset..new_offset + fragment.len,
1864 old_lines: Point::zero(),
1865 });
1866 self.delta += fragment.len as isize;
1867 }
1868 } else if fragment.was_visible(&self.since, &self.undos) && !fragment.visible {
1869 let deleted_start = self.cursor.start().deleted;
1870 let old_lines = self.deleted_text.to_point(deleted_start + fragment.len)
1871 - self.deleted_text.to_point(deleted_start);
1872 if let Some(ref mut change) = change {
1873 if change.new_range.end == new_offset {
1874 change.old_range.end += fragment.len;
1875 change.old_lines += &old_lines;
1876 self.delta -= fragment.len as isize;
1877 } else {
1878 break;
1879 }
1880 } else {
1881 change = Some(Edit {
1882 old_range: old_offset..old_offset + fragment.len,
1883 new_range: new_offset..new_offset,
1884 old_lines,
1885 });
1886 self.delta -= fragment.len as isize;
1887 }
1888 }
1889
1890 self.cursor.next(&None);
1891 }
1892
1893 change
1894 }
1895}
1896
1897struct ByteChunks<'a>(rope::Chunks<'a>);
1898
1899impl<'a> Iterator for ByteChunks<'a> {
1900 type Item = &'a [u8];
1901
1902 fn next(&mut self) -> Option<Self::Item> {
1903 self.0.next().map(str::as_bytes)
1904 }
1905}
1906
1907struct TextProvider<'a>(&'a Rope);
1908
1909impl<'a> tree_sitter::TextProvider<'a> for TextProvider<'a> {
1910 type I = ByteChunks<'a>;
1911
1912 fn text(&mut self, node: tree_sitter::Node) -> Self::I {
1913 ByteChunks(self.0.chunks_in_range(node.byte_range()))
1914 }
1915}
1916
1917struct Highlights<'a> {
1918 captures: tree_sitter::QueryCaptures<'a, 'a, TextProvider<'a>>,
1919 next_capture: Option<(tree_sitter::QueryMatch<'a, 'a>, usize)>,
1920 stack: Vec<(usize, StyleId)>,
1921 theme_mapping: ThemeMap,
1922}
1923
1924pub struct HighlightedChunks<'a> {
1925 range: Range<usize>,
1926 chunks: Chunks<'a>,
1927 highlights: Option<Highlights<'a>>,
1928}
1929
1930impl<'a> HighlightedChunks<'a> {
1931 pub fn seek(&mut self, offset: usize) {
1932 self.range.start = offset;
1933 self.chunks.seek(self.range.start);
1934 if let Some(highlights) = self.highlights.as_mut() {
1935 highlights
1936 .stack
1937 .retain(|(end_offset, _)| *end_offset > offset);
1938 if let Some((mat, capture_ix)) = &highlights.next_capture {
1939 let capture = mat.captures[*capture_ix as usize];
1940 if offset >= capture.node.start_byte() {
1941 let next_capture_end = capture.node.end_byte();
1942 if offset < next_capture_end {
1943 highlights.stack.push((
1944 next_capture_end,
1945 highlights.theme_mapping.get(capture.index),
1946 ));
1947 }
1948 highlights.next_capture.take();
1949 }
1950 }
1951 highlights.captures.set_byte_range(self.range.clone());
1952 }
1953 }
1954
1955 pub fn offset(&self) -> usize {
1956 self.range.start
1957 }
1958}
1959
1960impl<'a> Iterator for HighlightedChunks<'a> {
1961 type Item = (&'a str, StyleId);
1962
1963 fn next(&mut self) -> Option<Self::Item> {
1964 let mut next_capture_start = usize::MAX;
1965
1966 if let Some(highlights) = self.highlights.as_mut() {
1967 while let Some((parent_capture_end, _)) = highlights.stack.last() {
1968 if *parent_capture_end <= self.range.start {
1969 highlights.stack.pop();
1970 } else {
1971 break;
1972 }
1973 }
1974
1975 if highlights.next_capture.is_none() {
1976 highlights.next_capture = highlights.captures.next();
1977 }
1978
1979 while let Some((mat, capture_ix)) = highlights.next_capture.as_ref() {
1980 let capture = mat.captures[*capture_ix as usize];
1981 if self.range.start < capture.node.start_byte() {
1982 next_capture_start = capture.node.start_byte();
1983 break;
1984 } else {
1985 let style_id = highlights.theme_mapping.get(capture.index);
1986 highlights.stack.push((capture.node.end_byte(), style_id));
1987 highlights.next_capture = highlights.captures.next();
1988 }
1989 }
1990 }
1991
1992 if let Some(chunk) = self.chunks.peek() {
1993 let chunk_start = self.range.start;
1994 let mut chunk_end = (self.chunks.offset() + chunk.len()).min(next_capture_start);
1995 let mut style_id = StyleId::default();
1996 if let Some((parent_capture_end, parent_style_id)) =
1997 self.highlights.as_ref().and_then(|h| h.stack.last())
1998 {
1999 chunk_end = chunk_end.min(*parent_capture_end);
2000 style_id = *parent_style_id;
2001 }
2002
2003 let slice =
2004 &chunk[chunk_start - self.chunks.offset()..chunk_end - self.chunks.offset()];
2005 self.range.start = chunk_end;
2006 if self.range.start == self.chunks.offset() + chunk.len() {
2007 self.chunks.next().unwrap();
2008 }
2009
2010 Some((slice, style_id))
2011 } else {
2012 None
2013 }
2014 }
2015}
2016
2017impl Fragment {
2018 fn is_visible(&self, undos: &UndoMap) -> bool {
2019 !undos.is_undone(self.timestamp.local())
2020 && self.deletions.iter().all(|d| undos.is_undone(*d))
2021 }
2022
2023 fn was_visible(&self, version: &time::Global, undos: &UndoMap) -> bool {
2024 (version.observed(self.timestamp.local())
2025 && !undos.was_undone(self.timestamp.local(), version))
2026 && self
2027 .deletions
2028 .iter()
2029 .all(|d| !version.observed(*d) || undos.was_undone(*d, version))
2030 }
2031}
2032
2033impl sum_tree::Item for Fragment {
2034 type Summary = FragmentSummary;
2035
2036 fn summary(&self) -> Self::Summary {
2037 let mut max_version = time::Global::new();
2038 max_version.observe(self.timestamp.local());
2039 for deletion in &self.deletions {
2040 max_version.observe(*deletion);
2041 }
2042 max_version.join(&self.max_undos);
2043
2044 let mut min_insertion_version = time::Global::new();
2045 min_insertion_version.observe(self.timestamp.local());
2046 let max_insertion_version = min_insertion_version.clone();
2047 if self.visible {
2048 FragmentSummary {
2049 text: FragmentTextSummary {
2050 visible: self.len,
2051 deleted: 0,
2052 },
2053 max_version,
2054 min_insertion_version,
2055 max_insertion_version,
2056 }
2057 } else {
2058 FragmentSummary {
2059 text: FragmentTextSummary {
2060 visible: 0,
2061 deleted: self.len,
2062 },
2063 max_version,
2064 min_insertion_version,
2065 max_insertion_version,
2066 }
2067 }
2068 }
2069}
2070
2071impl sum_tree::Summary for FragmentSummary {
2072 type Context = Option<time::Global>;
2073
2074 fn add_summary(&mut self, other: &Self, _: &Self::Context) {
2075 self.text.visible += &other.text.visible;
2076 self.text.deleted += &other.text.deleted;
2077 self.max_version.join(&other.max_version);
2078 self.min_insertion_version
2079 .meet(&other.min_insertion_version);
2080 self.max_insertion_version
2081 .join(&other.max_insertion_version);
2082 }
2083}
2084
2085impl Default for FragmentSummary {
2086 fn default() -> Self {
2087 FragmentSummary {
2088 text: FragmentTextSummary::default(),
2089 max_version: time::Global::new(),
2090 min_insertion_version: time::Global::new(),
2091 max_insertion_version: time::Global::new(),
2092 }
2093 }
2094}
2095
2096impl<'a> sum_tree::Dimension<'a, FragmentSummary> for usize {
2097 fn add_summary(&mut self, summary: &FragmentSummary, _: &Option<time::Global>) {
2098 *self += summary.text.visible;
2099 }
2100}
2101
2102#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2103enum VersionedOffset {
2104 Offset(usize),
2105 InvalidVersion,
2106}
2107
2108impl VersionedOffset {
2109 fn offset(&self) -> usize {
2110 if let Self::Offset(offset) = self {
2111 *offset
2112 } else {
2113 panic!("invalid version")
2114 }
2115 }
2116}
2117
2118impl Default for VersionedOffset {
2119 fn default() -> Self {
2120 Self::Offset(0)
2121 }
2122}
2123
2124impl<'a> sum_tree::Dimension<'a, FragmentSummary> for VersionedOffset {
2125 fn add_summary(&mut self, summary: &'a FragmentSummary, cx: &Option<time::Global>) {
2126 if let Self::Offset(offset) = self {
2127 let version = cx.as_ref().unwrap();
2128 if *version >= summary.max_insertion_version {
2129 *offset += summary.text.visible + summary.text.deleted;
2130 } else if !summary
2131 .min_insertion_version
2132 .iter()
2133 .all(|t| !version.observed(*t))
2134 {
2135 *self = Self::InvalidVersion;
2136 }
2137 }
2138 }
2139}
2140
2141impl<'a> sum_tree::SeekDimension<'a, FragmentSummary> for VersionedOffset {
2142 fn cmp(&self, other: &Self, _: &Option<time::Global>) -> cmp::Ordering {
2143 match (self, other) {
2144 (Self::Offset(a), Self::Offset(b)) => Ord::cmp(a, b),
2145 (Self::Offset(_), Self::InvalidVersion) => cmp::Ordering::Less,
2146 (Self::InvalidVersion, _) => unreachable!(),
2147 }
2148 }
2149}
2150
2151impl Operation {
2152 fn replica_id(&self) -> ReplicaId {
2153 self.lamport_timestamp().replica_id
2154 }
2155
2156 fn lamport_timestamp(&self) -> time::Lamport {
2157 match self {
2158 Operation::Edit(edit) => edit.timestamp.lamport(),
2159 Operation::Undo {
2160 lamport_timestamp, ..
2161 } => *lamport_timestamp,
2162 Operation::UpdateSelections {
2163 lamport_timestamp, ..
2164 } => *lamport_timestamp,
2165 }
2166 }
2167
2168 pub fn is_edit(&self) -> bool {
2169 match self {
2170 Operation::Edit { .. } => true,
2171 _ => false,
2172 }
2173 }
2174}
2175
2176impl operation_queue::Operation for Operation {
2177 fn timestamp(&self) -> time::Lamport {
2178 self.lamport_timestamp()
2179 }
2180}
2181
2182pub trait ToOffset {
2183 fn to_offset(&self, buffer: &Buffer) -> usize;
2184}
2185
2186impl ToOffset for Point {
2187 fn to_offset(&self, buffer: &Buffer) -> usize {
2188 buffer.visible_text.to_offset(*self)
2189 }
2190}
2191
2192impl ToOffset for usize {
2193 fn to_offset(&self, _: &Buffer) -> usize {
2194 *self
2195 }
2196}
2197
2198impl ToOffset for Anchor {
2199 fn to_offset(&self, buffer: &Buffer) -> usize {
2200 buffer.summary_for_anchor(self).bytes
2201 }
2202}
2203
2204impl<'a> ToOffset for &'a Anchor {
2205 fn to_offset(&self, buffer: &Buffer) -> usize {
2206 buffer.summary_for_anchor(self).bytes
2207 }
2208}
2209
2210pub trait ToPoint {
2211 fn to_point(&self, buffer: &Buffer) -> Point;
2212}
2213
2214impl ToPoint for Anchor {
2215 fn to_point(&self, buffer: &Buffer) -> Point {
2216 buffer.summary_for_anchor(self).lines
2217 }
2218}
2219
2220impl ToPoint for usize {
2221 fn to_point(&self, buffer: &Buffer) -> Point {
2222 buffer.visible_text.to_point(*self)
2223 }
2224}
2225
2226#[cfg(test)]
2227mod tests {
2228 use super::*;
2229 use crate::{
2230 test::{build_app_state, temp_tree},
2231 util::RandomCharIter,
2232 worktree::{Worktree, WorktreeHandle},
2233 };
2234 use gpui::{App, ModelHandle};
2235 use rand::prelude::*;
2236 use serde_json::json;
2237 use std::{
2238 cell::RefCell,
2239 cmp::Ordering,
2240 env, fs,
2241 iter::FromIterator,
2242 rc::Rc,
2243 sync::atomic::{self, AtomicUsize},
2244 };
2245
2246 #[gpui::test]
2247 fn test_edit(cx: &mut gpui::MutableAppContext) {
2248 cx.add_model(|cx| {
2249 let mut buffer = Buffer::new(0, "abc", cx);
2250 assert_eq!(buffer.text(), "abc");
2251 buffer.edit(vec![3..3], "def", None).unwrap();
2252 assert_eq!(buffer.text(), "abcdef");
2253 buffer.edit(vec![0..0], "ghi", None).unwrap();
2254 assert_eq!(buffer.text(), "ghiabcdef");
2255 buffer.edit(vec![5..5], "jkl", None).unwrap();
2256 assert_eq!(buffer.text(), "ghiabjklcdef");
2257 buffer.edit(vec![6..7], "", None).unwrap();
2258 assert_eq!(buffer.text(), "ghiabjlcdef");
2259 buffer.edit(vec![4..9], "mno", None).unwrap();
2260 assert_eq!(buffer.text(), "ghiamnoef");
2261 buffer
2262 });
2263 }
2264
2265 #[gpui::test]
2266 fn test_edit_events(cx: &mut gpui::MutableAppContext) {
2267 let mut now = Instant::now();
2268 let buffer_1_events = Rc::new(RefCell::new(Vec::new()));
2269 let buffer_2_events = Rc::new(RefCell::new(Vec::new()));
2270
2271 let buffer1 = cx.add_model(|cx| Buffer::new(0, "abcdef", cx));
2272 let buffer2 = cx.add_model(|cx| Buffer::new(1, "abcdef", cx));
2273 let mut buffer_ops = Vec::new();
2274 buffer1.update(cx, |buffer, cx| {
2275 let buffer_1_events = buffer_1_events.clone();
2276 cx.subscribe(&buffer1, move |_, event, _| {
2277 buffer_1_events.borrow_mut().push(event.clone())
2278 });
2279 let buffer_2_events = buffer_2_events.clone();
2280 cx.subscribe(&buffer2, move |_, event, _| {
2281 buffer_2_events.borrow_mut().push(event.clone())
2282 });
2283
2284 // An edit emits an edited event, followed by a dirtied event,
2285 // since the buffer was previously in a clean state.
2286 let op = buffer.edit(Some(2..4), "XYZ", Some(cx)).unwrap();
2287 buffer_ops.push(op);
2288
2289 // An empty transaction does not emit any events.
2290 buffer.start_transaction(None).unwrap();
2291 buffer.end_transaction(None, Some(cx)).unwrap();
2292
2293 // A transaction containing two edits emits one edited event.
2294 now += Duration::from_secs(1);
2295 buffer.start_transaction_at(None, now).unwrap();
2296 buffer_ops.push(buffer.edit(Some(5..5), "u", Some(cx)).unwrap());
2297 buffer_ops.push(buffer.edit(Some(6..6), "w", Some(cx)).unwrap());
2298 buffer.end_transaction_at(None, now, Some(cx)).unwrap();
2299
2300 // Undoing a transaction emits one edited event.
2301 let ops = buffer.undo(Some(cx));
2302 buffer_ops.extend_from_slice(&ops);
2303 });
2304
2305 // Incorporating a set of remote ops emits a single edited event,
2306 // followed by a dirtied event.
2307 buffer2.update(cx, |buffer, cx| {
2308 buffer.apply_ops(buffer_ops, Some(cx)).unwrap();
2309 });
2310
2311 let buffer_1_events = buffer_1_events.borrow();
2312 assert_eq!(
2313 *buffer_1_events,
2314 vec![Event::Edited, Event::Dirtied, Event::Edited, Event::Edited]
2315 );
2316
2317 let buffer_2_events = buffer_2_events.borrow();
2318 assert_eq!(*buffer_2_events, vec![Event::Edited, Event::Dirtied]);
2319 }
2320
2321 #[gpui::test]
2322 fn test_random_edits(cx: &mut gpui::MutableAppContext) {
2323 let iterations = env::var("ITERATIONS")
2324 .map(|i| i.parse().expect("invalid `ITERATIONS` variable"))
2325 .unwrap_or(100);
2326 let operations = env::var("OPERATIONS")
2327 .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
2328 .unwrap_or(10);
2329 let start_seed =
2330 env::var("SEED").map_or(0, |seed| seed.parse().expect("invalid `SEED` variable"));
2331
2332 for seed in start_seed..start_seed + iterations {
2333 println!("{:?}", seed);
2334 let mut rng = &mut StdRng::seed_from_u64(seed);
2335
2336 let reference_string_len = rng.gen_range(0..3);
2337 let mut reference_string = RandomCharIter::new(&mut rng)
2338 .take(reference_string_len)
2339 .collect::<String>();
2340 cx.add_model(|cx| {
2341 let mut buffer = Buffer::new(0, reference_string.as_str(), cx);
2342 let mut buffer_versions = Vec::new();
2343 log::info!(
2344 "buffer text {:?}, version: {:?}",
2345 buffer.text(),
2346 buffer.version()
2347 );
2348
2349 for _i in 0..operations {
2350 let (old_ranges, new_text, _) = buffer.randomly_mutate(rng, None);
2351 for old_range in old_ranges.iter().rev() {
2352 reference_string.replace_range(old_range.clone(), &new_text);
2353 }
2354 assert_eq!(buffer.text(), reference_string);
2355 log::info!(
2356 "buffer text {:?}, version: {:?}",
2357 buffer.text(),
2358 buffer.version()
2359 );
2360
2361 if rng.gen_bool(0.25) {
2362 buffer.randomly_undo_redo(rng);
2363 reference_string = buffer.text();
2364 }
2365
2366 let range = buffer.random_byte_range(0, rng);
2367 assert_eq!(
2368 buffer.text_summary_for_range(range.clone()),
2369 TextSummary::from(&reference_string[range])
2370 );
2371
2372 if rng.gen_bool(0.3) {
2373 buffer_versions.push(buffer.clone());
2374 }
2375 }
2376
2377 for mut old_buffer in buffer_versions {
2378 let edits = buffer
2379 .edits_since(old_buffer.version.clone())
2380 .collect::<Vec<_>>();
2381
2382 log::info!(
2383 "mutating old buffer version {:?}, text: {:?}, edits since: {:?}",
2384 old_buffer.version(),
2385 old_buffer.text(),
2386 edits,
2387 );
2388
2389 let mut delta = 0_isize;
2390 for Edit {
2391 old_range,
2392 new_range,
2393 ..
2394 } in edits
2395 {
2396 let old_len = old_range.end - old_range.start;
2397 let new_len = new_range.end - new_range.start;
2398 let old_start = (old_range.start as isize + delta) as usize;
2399 let new_text: String = buffer.text_for_range(new_range).collect();
2400 old_buffer.edit(Some(old_start..old_start + old_len), new_text, None);
2401
2402 delta += new_len as isize - old_len as isize;
2403 }
2404 assert_eq!(old_buffer.text(), buffer.text());
2405 }
2406
2407 buffer
2408 });
2409 }
2410 }
2411
2412 #[gpui::test]
2413 fn test_line_len(cx: &mut gpui::MutableAppContext) {
2414 cx.add_model(|cx| {
2415 let mut buffer = Buffer::new(0, "", cx);
2416 buffer.edit(vec![0..0], "abcd\nefg\nhij", None).unwrap();
2417 buffer.edit(vec![12..12], "kl\nmno", None).unwrap();
2418 buffer.edit(vec![18..18], "\npqrs\n", None).unwrap();
2419 buffer.edit(vec![18..21], "\nPQ", None).unwrap();
2420
2421 assert_eq!(buffer.line_len(0), 4);
2422 assert_eq!(buffer.line_len(1), 3);
2423 assert_eq!(buffer.line_len(2), 5);
2424 assert_eq!(buffer.line_len(3), 3);
2425 assert_eq!(buffer.line_len(4), 4);
2426 assert_eq!(buffer.line_len(5), 0);
2427 buffer
2428 });
2429 }
2430
2431 #[gpui::test]
2432 fn test_text_summary_for_range(cx: &mut gpui::MutableAppContext) {
2433 cx.add_model(|cx| {
2434 let buffer = Buffer::new(0, "ab\nefg\nhklm\nnopqrs\ntuvwxyz", cx);
2435 assert_eq!(
2436 buffer.text_summary_for_range(1..3),
2437 TextSummary {
2438 bytes: 2,
2439 lines: Point::new(1, 0),
2440 first_line_chars: 1,
2441 last_line_chars: 0,
2442 longest_row: 0,
2443 longest_row_chars: 1,
2444 }
2445 );
2446 assert_eq!(
2447 buffer.text_summary_for_range(1..12),
2448 TextSummary {
2449 bytes: 11,
2450 lines: Point::new(3, 0),
2451 first_line_chars: 1,
2452 last_line_chars: 0,
2453 longest_row: 2,
2454 longest_row_chars: 4,
2455 }
2456 );
2457 assert_eq!(
2458 buffer.text_summary_for_range(0..20),
2459 TextSummary {
2460 bytes: 20,
2461 lines: Point::new(4, 1),
2462 first_line_chars: 2,
2463 last_line_chars: 1,
2464 longest_row: 3,
2465 longest_row_chars: 6,
2466 }
2467 );
2468 assert_eq!(
2469 buffer.text_summary_for_range(0..22),
2470 TextSummary {
2471 bytes: 22,
2472 lines: Point::new(4, 3),
2473 first_line_chars: 2,
2474 last_line_chars: 3,
2475 longest_row: 3,
2476 longest_row_chars: 6,
2477 }
2478 );
2479 assert_eq!(
2480 buffer.text_summary_for_range(7..22),
2481 TextSummary {
2482 bytes: 15,
2483 lines: Point::new(2, 3),
2484 first_line_chars: 4,
2485 last_line_chars: 3,
2486 longest_row: 1,
2487 longest_row_chars: 6,
2488 }
2489 );
2490 buffer
2491 });
2492 }
2493
2494 #[gpui::test]
2495 fn test_chars_at(cx: &mut gpui::MutableAppContext) {
2496 cx.add_model(|cx| {
2497 let mut buffer = Buffer::new(0, "", cx);
2498 buffer.edit(vec![0..0], "abcd\nefgh\nij", None).unwrap();
2499 buffer.edit(vec![12..12], "kl\nmno", None).unwrap();
2500 buffer.edit(vec![18..18], "\npqrs", None).unwrap();
2501 buffer.edit(vec![18..21], "\nPQ", None).unwrap();
2502
2503 let chars = buffer.chars_at(Point::new(0, 0));
2504 assert_eq!(chars.collect::<String>(), "abcd\nefgh\nijkl\nmno\nPQrs");
2505
2506 let chars = buffer.chars_at(Point::new(1, 0));
2507 assert_eq!(chars.collect::<String>(), "efgh\nijkl\nmno\nPQrs");
2508
2509 let chars = buffer.chars_at(Point::new(2, 0));
2510 assert_eq!(chars.collect::<String>(), "ijkl\nmno\nPQrs");
2511
2512 let chars = buffer.chars_at(Point::new(3, 0));
2513 assert_eq!(chars.collect::<String>(), "mno\nPQrs");
2514
2515 let chars = buffer.chars_at(Point::new(4, 0));
2516 assert_eq!(chars.collect::<String>(), "PQrs");
2517
2518 // Regression test:
2519 let mut buffer = Buffer::new(0, "", cx);
2520 buffer.edit(vec![0..0], "[workspace]\nmembers = [\n \"xray_core\",\n \"xray_server\",\n \"xray_cli\",\n \"xray_wasm\",\n]\n", None).unwrap();
2521 buffer.edit(vec![60..60], "\n", None).unwrap();
2522
2523 let chars = buffer.chars_at(Point::new(6, 0));
2524 assert_eq!(chars.collect::<String>(), " \"xray_wasm\",\n]\n");
2525
2526 buffer
2527 });
2528 }
2529
2530 #[gpui::test]
2531 fn test_anchors(cx: &mut gpui::MutableAppContext) {
2532 cx.add_model(|cx| {
2533 let mut buffer = Buffer::new(0, "", cx);
2534 buffer.edit(vec![0..0], "abc", None).unwrap();
2535 let left_anchor = buffer.anchor_before(2);
2536 let right_anchor = buffer.anchor_after(2);
2537
2538 buffer.edit(vec![1..1], "def\n", None).unwrap();
2539 assert_eq!(buffer.text(), "adef\nbc");
2540 assert_eq!(left_anchor.to_offset(&buffer), 6);
2541 assert_eq!(right_anchor.to_offset(&buffer), 6);
2542 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
2543 assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 1 });
2544
2545 buffer.edit(vec![2..3], "", None).unwrap();
2546 assert_eq!(buffer.text(), "adf\nbc");
2547 assert_eq!(left_anchor.to_offset(&buffer), 5);
2548 assert_eq!(right_anchor.to_offset(&buffer), 5);
2549 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
2550 assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 1 });
2551
2552 buffer.edit(vec![5..5], "ghi\n", None).unwrap();
2553 assert_eq!(buffer.text(), "adf\nbghi\nc");
2554 assert_eq!(left_anchor.to_offset(&buffer), 5);
2555 assert_eq!(right_anchor.to_offset(&buffer), 9);
2556 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
2557 assert_eq!(right_anchor.to_point(&buffer), Point { row: 2, column: 0 });
2558
2559 buffer.edit(vec![7..9], "", None).unwrap();
2560 assert_eq!(buffer.text(), "adf\nbghc");
2561 assert_eq!(left_anchor.to_offset(&buffer), 5);
2562 assert_eq!(right_anchor.to_offset(&buffer), 7);
2563 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 },);
2564 assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 3 });
2565
2566 // Ensure anchoring to a point is equivalent to anchoring to an offset.
2567 assert_eq!(
2568 buffer.anchor_before(Point { row: 0, column: 0 }),
2569 buffer.anchor_before(0)
2570 );
2571 assert_eq!(
2572 buffer.anchor_before(Point { row: 0, column: 1 }),
2573 buffer.anchor_before(1)
2574 );
2575 assert_eq!(
2576 buffer.anchor_before(Point { row: 0, column: 2 }),
2577 buffer.anchor_before(2)
2578 );
2579 assert_eq!(
2580 buffer.anchor_before(Point { row: 0, column: 3 }),
2581 buffer.anchor_before(3)
2582 );
2583 assert_eq!(
2584 buffer.anchor_before(Point { row: 1, column: 0 }),
2585 buffer.anchor_before(4)
2586 );
2587 assert_eq!(
2588 buffer.anchor_before(Point { row: 1, column: 1 }),
2589 buffer.anchor_before(5)
2590 );
2591 assert_eq!(
2592 buffer.anchor_before(Point { row: 1, column: 2 }),
2593 buffer.anchor_before(6)
2594 );
2595 assert_eq!(
2596 buffer.anchor_before(Point { row: 1, column: 3 }),
2597 buffer.anchor_before(7)
2598 );
2599 assert_eq!(
2600 buffer.anchor_before(Point { row: 1, column: 4 }),
2601 buffer.anchor_before(8)
2602 );
2603
2604 // Comparison between anchors.
2605 let anchor_at_offset_0 = buffer.anchor_before(0);
2606 let anchor_at_offset_1 = buffer.anchor_before(1);
2607 let anchor_at_offset_2 = buffer.anchor_before(2);
2608
2609 assert_eq!(
2610 anchor_at_offset_0
2611 .cmp(&anchor_at_offset_0, &buffer)
2612 .unwrap(),
2613 Ordering::Equal
2614 );
2615 assert_eq!(
2616 anchor_at_offset_1
2617 .cmp(&anchor_at_offset_1, &buffer)
2618 .unwrap(),
2619 Ordering::Equal
2620 );
2621 assert_eq!(
2622 anchor_at_offset_2
2623 .cmp(&anchor_at_offset_2, &buffer)
2624 .unwrap(),
2625 Ordering::Equal
2626 );
2627
2628 assert_eq!(
2629 anchor_at_offset_0
2630 .cmp(&anchor_at_offset_1, &buffer)
2631 .unwrap(),
2632 Ordering::Less
2633 );
2634 assert_eq!(
2635 anchor_at_offset_1
2636 .cmp(&anchor_at_offset_2, &buffer)
2637 .unwrap(),
2638 Ordering::Less
2639 );
2640 assert_eq!(
2641 anchor_at_offset_0
2642 .cmp(&anchor_at_offset_2, &buffer)
2643 .unwrap(),
2644 Ordering::Less
2645 );
2646
2647 assert_eq!(
2648 anchor_at_offset_1
2649 .cmp(&anchor_at_offset_0, &buffer)
2650 .unwrap(),
2651 Ordering::Greater
2652 );
2653 assert_eq!(
2654 anchor_at_offset_2
2655 .cmp(&anchor_at_offset_1, &buffer)
2656 .unwrap(),
2657 Ordering::Greater
2658 );
2659 assert_eq!(
2660 anchor_at_offset_2
2661 .cmp(&anchor_at_offset_0, &buffer)
2662 .unwrap(),
2663 Ordering::Greater
2664 );
2665 buffer
2666 });
2667 }
2668
2669 #[gpui::test]
2670 fn test_anchors_at_start_and_end(cx: &mut gpui::MutableAppContext) {
2671 cx.add_model(|cx| {
2672 let mut buffer = Buffer::new(0, "", cx);
2673 let before_start_anchor = buffer.anchor_before(0);
2674 let after_end_anchor = buffer.anchor_after(0);
2675
2676 buffer.edit(vec![0..0], "abc", None).unwrap();
2677 assert_eq!(buffer.text(), "abc");
2678 assert_eq!(before_start_anchor.to_offset(&buffer), 0);
2679 assert_eq!(after_end_anchor.to_offset(&buffer), 3);
2680
2681 let after_start_anchor = buffer.anchor_after(0);
2682 let before_end_anchor = buffer.anchor_before(3);
2683
2684 buffer.edit(vec![3..3], "def", None).unwrap();
2685 buffer.edit(vec![0..0], "ghi", None).unwrap();
2686 assert_eq!(buffer.text(), "ghiabcdef");
2687 assert_eq!(before_start_anchor.to_offset(&buffer), 0);
2688 assert_eq!(after_start_anchor.to_offset(&buffer), 3);
2689 assert_eq!(before_end_anchor.to_offset(&buffer), 6);
2690 assert_eq!(after_end_anchor.to_offset(&buffer), 9);
2691 buffer
2692 });
2693 }
2694
2695 #[test]
2696 fn test_is_dirty() {
2697 App::test_async((), |mut cx| async move {
2698 let dir = temp_tree(json!({
2699 "file1": "",
2700 "file2": "",
2701 "file3": "",
2702 }));
2703 let tree = cx.add_model(|cx| Worktree::new(dir.path(), cx));
2704 tree.flush_fs_events(&cx).await;
2705 cx.read(|cx| tree.read(cx).scan_complete()).await;
2706
2707 let file1 = cx.update(|cx| tree.file("file1", cx)).await;
2708 let buffer1 = cx.add_model(|cx| {
2709 Buffer::from_history(0, History::new("abc".into()), Some(file1), None, cx)
2710 });
2711 let events = Rc::new(RefCell::new(Vec::new()));
2712
2713 // initially, the buffer isn't dirty.
2714 buffer1.update(&mut cx, |buffer, cx| {
2715 cx.subscribe(&buffer1, {
2716 let events = events.clone();
2717 move |_, event, _| events.borrow_mut().push(event.clone())
2718 });
2719
2720 assert!(!buffer.is_dirty());
2721 assert!(events.borrow().is_empty());
2722
2723 buffer.edit(vec![1..2], "", Some(cx)).unwrap();
2724 });
2725
2726 // after the first edit, the buffer is dirty, and emits a dirtied event.
2727 buffer1.update(&mut cx, |buffer, cx| {
2728 assert!(buffer.text() == "ac");
2729 assert!(buffer.is_dirty());
2730 assert_eq!(*events.borrow(), &[Event::Edited, Event::Dirtied]);
2731 events.borrow_mut().clear();
2732
2733 buffer.did_save(buffer.version(), None, cx);
2734 });
2735
2736 // after saving, the buffer is not dirty, and emits a saved event.
2737 buffer1.update(&mut cx, |buffer, cx| {
2738 assert!(!buffer.is_dirty());
2739 assert_eq!(*events.borrow(), &[Event::Saved]);
2740 events.borrow_mut().clear();
2741
2742 buffer.edit(vec![1..1], "B", Some(cx)).unwrap();
2743 buffer.edit(vec![2..2], "D", Some(cx)).unwrap();
2744 });
2745
2746 // after editing again, the buffer is dirty, and emits another dirty event.
2747 buffer1.update(&mut cx, |buffer, cx| {
2748 assert!(buffer.text() == "aBDc");
2749 assert!(buffer.is_dirty());
2750 assert_eq!(
2751 *events.borrow(),
2752 &[Event::Edited, Event::Dirtied, Event::Edited],
2753 );
2754 events.borrow_mut().clear();
2755
2756 // TODO - currently, after restoring the buffer to its
2757 // previously-saved state, the is still considered dirty.
2758 buffer.edit(vec![1..3], "", Some(cx)).unwrap();
2759 assert!(buffer.text() == "ac");
2760 assert!(buffer.is_dirty());
2761 });
2762
2763 assert_eq!(*events.borrow(), &[Event::Edited]);
2764
2765 // When a file is deleted, the buffer is considered dirty.
2766 let events = Rc::new(RefCell::new(Vec::new()));
2767 let file2 = cx.update(|cx| tree.file("file2", cx)).await;
2768 let buffer2 = cx.add_model(|cx: &mut ModelContext<Buffer>| {
2769 cx.subscribe(&cx.handle(), {
2770 let events = events.clone();
2771 move |_, event, _| events.borrow_mut().push(event.clone())
2772 });
2773
2774 Buffer::from_history(0, History::new("abc".into()), Some(file2), None, cx)
2775 });
2776
2777 fs::remove_file(dir.path().join("file2")).unwrap();
2778 buffer2.condition(&cx, |b, _| b.is_dirty()).await;
2779 assert_eq!(
2780 *events.borrow(),
2781 &[Event::Dirtied, Event::FileHandleChanged]
2782 );
2783
2784 // When a file is already dirty when deleted, we don't emit a Dirtied event.
2785 let events = Rc::new(RefCell::new(Vec::new()));
2786 let file3 = cx.update(|cx| tree.file("file3", cx)).await;
2787 let buffer3 = cx.add_model(|cx: &mut ModelContext<Buffer>| {
2788 cx.subscribe(&cx.handle(), {
2789 let events = events.clone();
2790 move |_, event, _| events.borrow_mut().push(event.clone())
2791 });
2792
2793 Buffer::from_history(0, History::new("abc".into()), Some(file3), None, cx)
2794 });
2795
2796 tree.flush_fs_events(&cx).await;
2797 buffer3.update(&mut cx, |buffer, cx| {
2798 buffer.edit(Some(0..0), "x", Some(cx)).unwrap();
2799 });
2800 events.borrow_mut().clear();
2801 fs::remove_file(dir.path().join("file3")).unwrap();
2802 buffer3
2803 .condition(&cx, |_, _| !events.borrow().is_empty())
2804 .await;
2805 assert_eq!(*events.borrow(), &[Event::FileHandleChanged]);
2806 cx.read(|cx| assert!(buffer3.read(cx).is_dirty()));
2807 });
2808 }
2809
2810 #[gpui::test]
2811 async fn test_file_changes_on_disk(mut cx: gpui::TestAppContext) {
2812 let initial_contents = "aaa\nbbbbb\nc\n";
2813 let dir = temp_tree(json!({ "the-file": initial_contents }));
2814 let tree = cx.add_model(|cx| Worktree::new(dir.path(), cx));
2815 cx.read(|cx| tree.read(cx).scan_complete()).await;
2816
2817 let abs_path = dir.path().join("the-file");
2818 let file = cx.update(|cx| tree.file("the-file", cx)).await;
2819 let buffer = cx.add_model(|cx| {
2820 Buffer::from_history(
2821 0,
2822 History::new(initial_contents.into()),
2823 Some(file),
2824 None,
2825 cx,
2826 )
2827 });
2828
2829 // Add a cursor at the start of each row.
2830 let (selection_set_id, _) = buffer.update(&mut cx, |buffer, cx| {
2831 assert!(!buffer.is_dirty());
2832 buffer.add_selection_set(
2833 (0..3)
2834 .map(|row| {
2835 let anchor = buffer.anchor_at(Point::new(row, 0), Bias::Right);
2836 Selection {
2837 id: row as usize,
2838 start: anchor.clone(),
2839 end: anchor,
2840 reversed: false,
2841 goal: SelectionGoal::None,
2842 }
2843 })
2844 .collect::<Vec<_>>(),
2845 Some(cx),
2846 )
2847 });
2848
2849 // Change the file on disk, adding two new lines of text, and removing
2850 // one line.
2851 buffer.read_with(&cx, |buffer, _| {
2852 assert!(!buffer.is_dirty());
2853 assert!(!buffer.has_conflict());
2854 });
2855 let new_contents = "AAAA\naaa\nBB\nbbbbb\n";
2856 fs::write(&abs_path, new_contents).unwrap();
2857
2858 // Because the buffer was not modified, it is reloaded from disk. Its
2859 // contents are edited according to the diff between the old and new
2860 // file contents.
2861 buffer
2862 .condition(&cx, |buffer, _| buffer.text() != initial_contents)
2863 .await;
2864
2865 buffer.update(&mut cx, |buffer, _| {
2866 assert_eq!(buffer.text(), new_contents);
2867 assert!(!buffer.is_dirty());
2868 assert!(!buffer.has_conflict());
2869
2870 let selections = buffer.selections(selection_set_id).unwrap();
2871 let cursor_positions = selections
2872 .iter()
2873 .map(|selection| {
2874 assert_eq!(selection.start, selection.end);
2875 selection.start.to_point(&buffer)
2876 })
2877 .collect::<Vec<_>>();
2878 assert_eq!(
2879 cursor_positions,
2880 &[Point::new(1, 0), Point::new(3, 0), Point::new(4, 0),]
2881 );
2882 });
2883
2884 // Modify the buffer
2885 buffer.update(&mut cx, |buffer, cx| {
2886 buffer.edit(vec![0..0], " ", Some(cx)).unwrap();
2887 assert!(buffer.is_dirty());
2888 });
2889
2890 // Change the file on disk again, adding blank lines to the beginning.
2891 fs::write(&abs_path, "\n\n\nAAAA\naaa\nBB\nbbbbb\n").unwrap();
2892
2893 // Becaues the buffer is modified, it doesn't reload from disk, but is
2894 // marked as having a conflict.
2895 buffer
2896 .condition(&cx, |buffer, _| buffer.has_conflict())
2897 .await;
2898 }
2899
2900 #[gpui::test]
2901 async fn test_set_text_via_diff(mut cx: gpui::TestAppContext) {
2902 let text = "a\nbb\nccc\ndddd\neeeee\nffffff\n";
2903 let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
2904
2905 let text = "a\nccc\ndddd\nffffff\n";
2906 let diff = buffer.read_with(&cx, |b, cx| b.diff(text.into(), cx)).await;
2907 buffer.update(&mut cx, |b, cx| b.set_text_via_diff(diff, cx));
2908 cx.read(|cx| assert_eq!(buffer.read(cx).text(), text));
2909
2910 let text = "a\n1\n\nccc\ndd2dd\nffffff\n";
2911 let diff = buffer.read_with(&cx, |b, cx| b.diff(text.into(), cx)).await;
2912 buffer.update(&mut cx, |b, cx| b.set_text_via_diff(diff, cx));
2913 cx.read(|cx| assert_eq!(buffer.read(cx).text(), text));
2914 }
2915
2916 #[gpui::test]
2917 fn test_undo_redo(cx: &mut gpui::MutableAppContext) {
2918 cx.add_model(|cx| {
2919 let mut buffer = Buffer::new(0, "1234", cx);
2920
2921 let edit1 = buffer.edit(vec![1..1], "abx", None).unwrap();
2922 let edit2 = buffer.edit(vec![3..4], "yzef", None).unwrap();
2923 let edit3 = buffer.edit(vec![3..5], "cd", None).unwrap();
2924 assert_eq!(buffer.text(), "1abcdef234");
2925
2926 buffer.undo_or_redo(edit1.edit_id().unwrap()).unwrap();
2927 assert_eq!(buffer.text(), "1cdef234");
2928 buffer.undo_or_redo(edit1.edit_id().unwrap()).unwrap();
2929 assert_eq!(buffer.text(), "1abcdef234");
2930
2931 buffer.undo_or_redo(edit2.edit_id().unwrap()).unwrap();
2932 assert_eq!(buffer.text(), "1abcdx234");
2933 buffer.undo_or_redo(edit3.edit_id().unwrap()).unwrap();
2934 assert_eq!(buffer.text(), "1abx234");
2935 buffer.undo_or_redo(edit2.edit_id().unwrap()).unwrap();
2936 assert_eq!(buffer.text(), "1abyzef234");
2937 buffer.undo_or_redo(edit3.edit_id().unwrap()).unwrap();
2938 assert_eq!(buffer.text(), "1abcdef234");
2939
2940 buffer.undo_or_redo(edit3.edit_id().unwrap()).unwrap();
2941 assert_eq!(buffer.text(), "1abyzef234");
2942 buffer.undo_or_redo(edit1.edit_id().unwrap()).unwrap();
2943 assert_eq!(buffer.text(), "1yzef234");
2944 buffer.undo_or_redo(edit2.edit_id().unwrap()).unwrap();
2945 assert_eq!(buffer.text(), "1234");
2946
2947 buffer
2948 });
2949 }
2950
2951 #[gpui::test]
2952 fn test_history(cx: &mut gpui::MutableAppContext) {
2953 cx.add_model(|cx| {
2954 let mut now = Instant::now();
2955 let mut buffer = Buffer::new(0, "123456", cx);
2956
2957 let (set_id, _) =
2958 buffer.add_selection_set(buffer.selections_from_ranges(vec![4..4]).unwrap(), None);
2959 buffer.start_transaction_at(Some(set_id), now).unwrap();
2960 buffer.edit(vec![2..4], "cd", None).unwrap();
2961 buffer.end_transaction_at(Some(set_id), now, None).unwrap();
2962 assert_eq!(buffer.text(), "12cd56");
2963 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![4..4]);
2964
2965 buffer.start_transaction_at(Some(set_id), now).unwrap();
2966 buffer
2967 .update_selection_set(
2968 set_id,
2969 buffer.selections_from_ranges(vec![1..3]).unwrap(),
2970 None,
2971 )
2972 .unwrap();
2973 buffer.edit(vec![4..5], "e", None).unwrap();
2974 buffer.end_transaction_at(Some(set_id), now, None).unwrap();
2975 assert_eq!(buffer.text(), "12cde6");
2976 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
2977
2978 now += UNDO_GROUP_INTERVAL + Duration::from_millis(1);
2979 buffer.start_transaction_at(Some(set_id), now).unwrap();
2980 buffer
2981 .update_selection_set(
2982 set_id,
2983 buffer.selections_from_ranges(vec![2..2]).unwrap(),
2984 None,
2985 )
2986 .unwrap();
2987 buffer.edit(vec![0..1], "a", None).unwrap();
2988 buffer.edit(vec![1..1], "b", None).unwrap();
2989 buffer.end_transaction_at(Some(set_id), now, None).unwrap();
2990 assert_eq!(buffer.text(), "ab2cde6");
2991 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![3..3]);
2992
2993 // Last transaction happened past the group interval, undo it on its
2994 // own.
2995 buffer.undo(None);
2996 assert_eq!(buffer.text(), "12cde6");
2997 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
2998
2999 // First two transactions happened within the group interval, undo them
3000 // together.
3001 buffer.undo(None);
3002 assert_eq!(buffer.text(), "123456");
3003 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![4..4]);
3004
3005 // Redo the first two transactions together.
3006 buffer.redo(None);
3007 assert_eq!(buffer.text(), "12cde6");
3008 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
3009
3010 // Redo the last transaction on its own.
3011 buffer.redo(None);
3012 assert_eq!(buffer.text(), "ab2cde6");
3013 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![3..3]);
3014
3015 buffer
3016 });
3017 }
3018
3019 #[gpui::test]
3020 fn test_concurrent_edits(cx: &mut gpui::MutableAppContext) {
3021 let text = "abcdef";
3022
3023 let buffer1 = cx.add_model(|cx| Buffer::new(1, text, cx));
3024 let buffer2 = cx.add_model(|cx| Buffer::new(2, text, cx));
3025 let buffer3 = cx.add_model(|cx| Buffer::new(3, text, cx));
3026
3027 let buf1_op = buffer1.update(cx, |buffer, cx| {
3028 let op = buffer.edit(vec![1..2], "12", Some(cx)).unwrap();
3029 assert_eq!(buffer.text(), "a12cdef");
3030 op
3031 });
3032 let buf2_op = buffer2.update(cx, |buffer, cx| {
3033 let op = buffer.edit(vec![3..4], "34", Some(cx)).unwrap();
3034 assert_eq!(buffer.text(), "abc34ef");
3035 op
3036 });
3037 let buf3_op = buffer3.update(cx, |buffer, cx| {
3038 let op = buffer.edit(vec![5..6], "56", Some(cx)).unwrap();
3039 assert_eq!(buffer.text(), "abcde56");
3040 op
3041 });
3042
3043 buffer1.update(cx, |buffer, _| {
3044 buffer.apply_op(buf2_op.clone()).unwrap();
3045 buffer.apply_op(buf3_op.clone()).unwrap();
3046 });
3047 buffer2.update(cx, |buffer, _| {
3048 buffer.apply_op(buf1_op.clone()).unwrap();
3049 buffer.apply_op(buf3_op.clone()).unwrap();
3050 });
3051 buffer3.update(cx, |buffer, _| {
3052 buffer.apply_op(buf1_op.clone()).unwrap();
3053 buffer.apply_op(buf2_op.clone()).unwrap();
3054 });
3055
3056 assert_eq!(buffer1.read(cx).text(), "a12c34e56");
3057 assert_eq!(buffer2.read(cx).text(), "a12c34e56");
3058 assert_eq!(buffer3.read(cx).text(), "a12c34e56");
3059 }
3060
3061 #[gpui::test]
3062 fn test_random_concurrent_edits(cx: &mut gpui::MutableAppContext) {
3063 use crate::test::Network;
3064
3065 let peers = env::var("PEERS")
3066 .map(|i| i.parse().expect("invalid `PEERS` variable"))
3067 .unwrap_or(5);
3068 let iterations = env::var("ITERATIONS")
3069 .map(|i| i.parse().expect("invalid `ITERATIONS` variable"))
3070 .unwrap_or(100);
3071 let operations = env::var("OPERATIONS")
3072 .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
3073 .unwrap_or(10);
3074 let start_seed =
3075 env::var("SEED").map_or(0, |seed| seed.parse().expect("invalid `SEED` variable"));
3076
3077 for seed in start_seed..start_seed + iterations {
3078 dbg!(seed);
3079 let mut rng = &mut StdRng::seed_from_u64(seed);
3080
3081 let base_text_len = rng.gen_range(0..10);
3082 let base_text = RandomCharIter::new(&mut rng)
3083 .take(base_text_len)
3084 .collect::<String>();
3085 let mut replica_ids = Vec::new();
3086 let mut buffers = Vec::new();
3087 let mut network = Network::new();
3088 for i in 0..peers {
3089 let buffer = cx.add_model(|cx| Buffer::new(i as ReplicaId, base_text.as_str(), cx));
3090 buffers.push(buffer);
3091 replica_ids.push(i as u16);
3092 network.add_peer(i as u16);
3093 }
3094
3095 log::info!("initial text: {:?}", base_text);
3096
3097 let mut mutation_count = operations;
3098 loop {
3099 let replica_index = rng.gen_range(0..peers);
3100 let replica_id = replica_ids[replica_index];
3101 buffers[replica_index].update(cx, |buffer, _| match rng.gen_range(0..=100) {
3102 0..=50 if mutation_count != 0 => {
3103 let (_, _, ops) = buffer.randomly_mutate(&mut rng, None);
3104 log::info!("buffer {} text: {:?}", buffer.replica_id, buffer.text());
3105 network.broadcast(replica_id, ops, &mut rng);
3106 mutation_count -= 1;
3107 }
3108 51..=70 if mutation_count != 0 => {
3109 let ops = buffer.randomly_undo_redo(&mut rng);
3110 network.broadcast(replica_id, ops, &mut rng);
3111 mutation_count -= 1;
3112 }
3113 71..=100 if network.has_unreceived(replica_id) => {
3114 let ops = network.receive(replica_id, &mut rng);
3115 if !ops.is_empty() {
3116 log::info!(
3117 "peer {} applying {} ops from the network.",
3118 replica_id,
3119 ops.len()
3120 );
3121 buffer.apply_ops(ops, None).unwrap();
3122 }
3123 }
3124 _ => {}
3125 });
3126
3127 if mutation_count == 0 && network.is_idle() {
3128 break;
3129 }
3130 }
3131
3132 let first_buffer = buffers[0].read(cx);
3133 for buffer in &buffers[1..] {
3134 let buffer = buffer.read(cx);
3135 assert_eq!(
3136 buffer.text(),
3137 first_buffer.text(),
3138 "Replica {} text != Replica 0 text",
3139 buffer.replica_id
3140 );
3141 assert_eq!(
3142 buffer.all_selections().collect::<HashMap<_, _>>(),
3143 first_buffer.all_selections().collect::<HashMap<_, _>>()
3144 );
3145 assert_eq!(
3146 buffer.all_selection_ranges().collect::<HashMap<_, _>>(),
3147 first_buffer
3148 .all_selection_ranges()
3149 .collect::<HashMap<_, _>>()
3150 );
3151 }
3152 }
3153 }
3154
3155 #[gpui::test]
3156 async fn test_reparse(mut cx: gpui::TestAppContext) {
3157 let app_state = cx.read(build_app_state);
3158 let rust_lang = app_state.language_registry.select_language("test.rs");
3159 assert!(rust_lang.is_some());
3160
3161 let buffer = cx.add_model(|cx| {
3162 let text = "fn a() {}".into();
3163 let buffer = Buffer::from_history(0, History::new(text), None, rust_lang.cloned(), cx);
3164 assert!(buffer.is_parsing());
3165 assert!(buffer.syntax_tree().is_none());
3166 buffer
3167 });
3168
3169 // Wait for the initial text to parse
3170 buffer
3171 .condition(&cx, |buffer, _| !buffer.is_parsing())
3172 .await;
3173 assert_eq!(
3174 get_tree_sexp(&buffer, &cx),
3175 concat!(
3176 "(source_file (function_item name: (identifier) ",
3177 "parameters: (parameters) ",
3178 "body: (block)))"
3179 )
3180 );
3181
3182 // Perform some edits (add parameter and variable reference)
3183 // Parsing doesn't begin until the transaction is complete
3184 buffer.update(&mut cx, |buf, cx| {
3185 buf.start_transaction(None).unwrap();
3186
3187 let offset = buf.text().find(")").unwrap();
3188 buf.edit(vec![offset..offset], "b: C", Some(cx)).unwrap();
3189 assert!(!buf.is_parsing());
3190
3191 let offset = buf.text().find("}").unwrap();
3192 buf.edit(vec![offset..offset], " d; ", Some(cx)).unwrap();
3193 assert!(!buf.is_parsing());
3194
3195 buf.end_transaction(None, Some(cx)).unwrap();
3196 assert_eq!(buf.text(), "fn a(b: C) { d; }");
3197 assert!(buf.is_parsing());
3198 });
3199 buffer
3200 .condition(&cx, |buffer, _| !buffer.is_parsing())
3201 .await;
3202 assert_eq!(
3203 get_tree_sexp(&buffer, &cx),
3204 concat!(
3205 "(source_file (function_item name: (identifier) ",
3206 "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
3207 "body: (block (identifier))))"
3208 )
3209 );
3210
3211 // Perform a series of edits without waiting for the current parse to complete:
3212 // * turn identifier into a field expression
3213 // * turn field expression into a method call
3214 // * add a turbofish to the method call
3215 buffer.update(&mut cx, |buf, cx| {
3216 let offset = buf.text().find(";").unwrap();
3217 buf.edit(vec![offset..offset], ".e", Some(cx)).unwrap();
3218 assert_eq!(buf.text(), "fn a(b: C) { d.e; }");
3219 assert!(buf.is_parsing());
3220 });
3221 buffer.update(&mut cx, |buf, cx| {
3222 let offset = buf.text().find(";").unwrap();
3223 buf.edit(vec![offset..offset], "(f)", Some(cx)).unwrap();
3224 assert_eq!(buf.text(), "fn a(b: C) { d.e(f); }");
3225 assert!(buf.is_parsing());
3226 });
3227 buffer.update(&mut cx, |buf, cx| {
3228 let offset = buf.text().find("(f)").unwrap();
3229 buf.edit(vec![offset..offset], "::<G>", Some(cx)).unwrap();
3230 assert_eq!(buf.text(), "fn a(b: C) { d.e::<G>(f); }");
3231 assert!(buf.is_parsing());
3232 });
3233 buffer
3234 .condition(&cx, |buffer, _| !buffer.is_parsing())
3235 .await;
3236 assert_eq!(
3237 get_tree_sexp(&buffer, &cx),
3238 concat!(
3239 "(source_file (function_item name: (identifier) ",
3240 "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
3241 "body: (block (call_expression ",
3242 "function: (generic_function ",
3243 "function: (field_expression value: (identifier) field: (field_identifier)) ",
3244 "type_arguments: (type_arguments (type_identifier))) ",
3245 "arguments: (arguments (identifier))))))",
3246 )
3247 );
3248
3249 buffer.update(&mut cx, |buf, cx| {
3250 buf.undo(Some(cx));
3251 assert_eq!(buf.text(), "fn a() {}");
3252 assert!(buf.is_parsing());
3253 });
3254 buffer
3255 .condition(&cx, |buffer, _| !buffer.is_parsing())
3256 .await;
3257 assert_eq!(
3258 get_tree_sexp(&buffer, &cx),
3259 concat!(
3260 "(source_file (function_item name: (identifier) ",
3261 "parameters: (parameters) ",
3262 "body: (block)))"
3263 )
3264 );
3265
3266 buffer.update(&mut cx, |buf, cx| {
3267 buf.redo(Some(cx));
3268 assert_eq!(buf.text(), "fn a(b: C) { d.e::<G>(f); }");
3269 assert!(buf.is_parsing());
3270 });
3271 buffer
3272 .condition(&cx, |buffer, _| !buffer.is_parsing())
3273 .await;
3274 assert_eq!(
3275 get_tree_sexp(&buffer, &cx),
3276 concat!(
3277 "(source_file (function_item name: (identifier) ",
3278 "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
3279 "body: (block (call_expression ",
3280 "function: (generic_function ",
3281 "function: (field_expression value: (identifier) field: (field_identifier)) ",
3282 "type_arguments: (type_arguments (type_identifier))) ",
3283 "arguments: (arguments (identifier))))))",
3284 )
3285 );
3286
3287 fn get_tree_sexp(buffer: &ModelHandle<Buffer>, cx: &gpui::TestAppContext) -> String {
3288 buffer.read_with(cx, |buffer, _| {
3289 buffer.syntax_tree().unwrap().root_node().to_sexp()
3290 })
3291 }
3292 }
3293
3294 #[gpui::test]
3295 async fn test_enclosing_bracket_ranges(mut cx: gpui::TestAppContext) {
3296 use unindent::Unindent as _;
3297
3298 let app_state = cx.read(build_app_state);
3299 let rust_lang = app_state.language_registry.select_language("test.rs");
3300 assert!(rust_lang.is_some());
3301
3302 let buffer = cx.add_model(|cx| {
3303 let text = "
3304 mod x {
3305 mod y {
3306
3307 }
3308 }
3309 "
3310 .unindent()
3311 .into();
3312 Buffer::from_history(0, History::new(text), None, rust_lang.cloned(), cx)
3313 });
3314 buffer
3315 .condition(&cx, |buffer, _| !buffer.is_parsing())
3316 .await;
3317 buffer.read_with(&cx, |buf, _| {
3318 assert_eq!(
3319 buf.enclosing_bracket_point_ranges(Point::new(1, 6)..Point::new(1, 6)),
3320 Some((
3321 Point::new(0, 6)..Point::new(0, 7),
3322 Point::new(4, 0)..Point::new(4, 1)
3323 ))
3324 );
3325 assert_eq!(
3326 buf.enclosing_bracket_point_ranges(Point::new(1, 10)..Point::new(1, 10)),
3327 Some((
3328 Point::new(1, 10)..Point::new(1, 11),
3329 Point::new(3, 4)..Point::new(3, 5)
3330 ))
3331 );
3332 assert_eq!(
3333 buf.enclosing_bracket_point_ranges(Point::new(3, 5)..Point::new(3, 5)),
3334 Some((
3335 Point::new(1, 10)..Point::new(1, 11),
3336 Point::new(3, 4)..Point::new(3, 5)
3337 ))
3338 );
3339 });
3340 }
3341
3342 impl Buffer {
3343 fn random_byte_range(&mut self, start_offset: usize, rng: &mut impl Rng) -> Range<usize> {
3344 let end = self.clip_offset(rng.gen_range(start_offset..=self.len()), Bias::Right);
3345 let start = self.clip_offset(rng.gen_range(start_offset..=end), Bias::Right);
3346 start..end
3347 }
3348
3349 pub fn randomly_edit<T>(
3350 &mut self,
3351 rng: &mut T,
3352 old_range_count: usize,
3353 cx: Option<&mut ModelContext<Self>>,
3354 ) -> (Vec<Range<usize>>, String, Option<Operation>)
3355 where
3356 T: Rng,
3357 {
3358 let mut old_ranges: Vec<Range<usize>> = Vec::new();
3359 for _ in 0..old_range_count {
3360 let last_end = old_ranges.last().map_or(0, |last_range| last_range.end + 1);
3361 if last_end > self.len() {
3362 break;
3363 }
3364 old_ranges.push(self.random_byte_range(last_end, rng));
3365 }
3366 let new_text_len = rng.gen_range(0..10);
3367 let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
3368 log::info!(
3369 "mutating buffer {} at {:?}: {:?}",
3370 self.replica_id,
3371 old_ranges,
3372 new_text
3373 );
3374 let operation = self.edit(old_ranges.iter().cloned(), new_text.as_str(), cx);
3375 (old_ranges, new_text, operation)
3376 }
3377
3378 pub fn randomly_mutate<T>(
3379 &mut self,
3380 rng: &mut T,
3381 mut cx: Option<&mut ModelContext<Self>>,
3382 ) -> (Vec<Range<usize>>, String, Vec<Operation>)
3383 where
3384 T: Rng,
3385 {
3386 let (old_ranges, new_text, operation) = self.randomly_edit(rng, 5, cx.as_deref_mut());
3387 let mut operations = Vec::from_iter(operation);
3388
3389 // Randomly add, remove or mutate selection sets.
3390 let replica_selection_sets = &self
3391 .all_selections()
3392 .map(|(set_id, _)| *set_id)
3393 .filter(|set_id| self.replica_id == set_id.replica_id)
3394 .collect::<Vec<_>>();
3395 let set_id = replica_selection_sets.choose(rng);
3396 if set_id.is_some() && rng.gen_bool(1.0 / 6.0) {
3397 let op = self.remove_selection_set(*set_id.unwrap(), None).unwrap();
3398 operations.push(op);
3399 } else {
3400 let mut ranges = Vec::new();
3401 for _ in 0..5 {
3402 ranges.push(self.random_byte_range(0, rng));
3403 }
3404 let new_selections = self.selections_from_ranges(ranges).unwrap();
3405
3406 let op = if set_id.is_none() || rng.gen_bool(1.0 / 5.0) {
3407 self.add_selection_set(new_selections, None).1
3408 } else {
3409 self.update_selection_set(*set_id.unwrap(), new_selections, None)
3410 .unwrap()
3411 };
3412 operations.push(op);
3413 }
3414
3415 (old_ranges, new_text, operations)
3416 }
3417
3418 pub fn randomly_undo_redo(&mut self, rng: &mut impl Rng) -> Vec<Operation> {
3419 let mut ops = Vec::new();
3420 for _ in 0..rng.gen_range(1..=5) {
3421 if let Some(edit_id) = self.history.ops.keys().choose(rng).copied() {
3422 log::info!("undoing buffer {} operation {:?}", self.replica_id, edit_id);
3423 ops.push(self.undo_or_redo(edit_id).unwrap());
3424 }
3425 }
3426 ops
3427 }
3428
3429 fn selections_from_ranges<I>(&self, ranges: I) -> Result<Vec<Selection>>
3430 where
3431 I: IntoIterator<Item = Range<usize>>,
3432 {
3433 static NEXT_SELECTION_ID: AtomicUsize = AtomicUsize::new(0);
3434
3435 let mut ranges = ranges.into_iter().collect::<Vec<_>>();
3436 ranges.sort_unstable_by_key(|range| range.start);
3437
3438 let mut selections = Vec::with_capacity(ranges.len());
3439 for range in ranges {
3440 if range.start > range.end {
3441 selections.push(Selection {
3442 id: NEXT_SELECTION_ID.fetch_add(1, atomic::Ordering::SeqCst),
3443 start: self.anchor_before(range.end),
3444 end: self.anchor_before(range.start),
3445 reversed: true,
3446 goal: SelectionGoal::None,
3447 });
3448 } else {
3449 selections.push(Selection {
3450 id: NEXT_SELECTION_ID.fetch_add(1, atomic::Ordering::SeqCst),
3451 start: self.anchor_after(range.start),
3452 end: self.anchor_before(range.end),
3453 reversed: false,
3454 goal: SelectionGoal::None,
3455 });
3456 }
3457 }
3458 Ok(selections)
3459 }
3460
3461 pub fn selection_ranges<'a>(&'a self, set_id: SelectionSetId) -> Result<Vec<Range<usize>>> {
3462 Ok(self
3463 .selections(set_id)?
3464 .iter()
3465 .map(move |selection| {
3466 let start = selection.start.to_offset(self);
3467 let end = selection.end.to_offset(self);
3468 if selection.reversed {
3469 end..start
3470 } else {
3471 start..end
3472 }
3473 })
3474 .collect())
3475 }
3476
3477 pub fn all_selections(&self) -> impl Iterator<Item = (&SelectionSetId, &[Selection])> {
3478 self.selections
3479 .iter()
3480 .map(|(set_id, selections)| (set_id, selections.as_ref()))
3481 }
3482
3483 pub fn all_selection_ranges<'a>(
3484 &'a self,
3485 ) -> impl 'a + Iterator<Item = (SelectionSetId, Vec<Range<usize>>)> {
3486 self.selections
3487 .keys()
3488 .map(move |set_id| (*set_id, self.selection_ranges(*set_id).unwrap()))
3489 }
3490
3491 pub fn enclosing_bracket_point_ranges<T: ToOffset>(
3492 &self,
3493 range: Range<T>,
3494 ) -> Option<(Range<Point>, Range<Point>)> {
3495 self.enclosing_bracket_ranges(range).map(|(start, end)| {
3496 let point_start = start.start.to_point(self)..start.end.to_point(self);
3497 let point_end = end.start.to_point(self)..end.end.to_point(self);
3498 (point_start, point_end)
3499 })
3500 }
3501 }
3502
3503 impl Operation {
3504 fn edit_id(&self) -> Option<time::Local> {
3505 match self {
3506 Operation::Edit(edit) => Some(edit.timestamp.local()),
3507 Operation::Undo { undo, .. } => Some(undo.edit_id),
3508 Operation::UpdateSelections { .. } => None,
3509 }
3510 }
3511 }
3512}