1mod anchor;
2mod highlight_map;
3mod language;
4mod operation_queue;
5mod point;
6#[cfg(any(test, feature = "test-support"))]
7pub mod random_char_iter;
8pub mod rope;
9mod selection;
10
11pub use anchor::*;
12use anyhow::{anyhow, Result};
13use clock::ReplicaId;
14use gpui::{AppContext, Entity, ModelContext, MutableAppContext, Task};
15pub use highlight_map::{HighlightId, HighlightMap};
16use language::Tree;
17pub use language::{AutoclosePair, Language, LanguageConfig, LanguageRegistry};
18use lazy_static::lazy_static;
19use operation_queue::OperationQueue;
20use parking_lot::Mutex;
21pub use point::*;
22#[cfg(any(test, feature = "test-support"))]
23pub use random_char_iter::*;
24pub use rope::{Chunks, Rope, TextSummary};
25use rpc::proto;
26use seahash::SeaHasher;
27pub use selection::*;
28use similar::{ChangeTag, TextDiff};
29use std::{
30 any::Any,
31 cell::RefCell,
32 cmp,
33 collections::BTreeMap,
34 convert::{TryFrom, TryInto},
35 ffi::OsString,
36 future::Future,
37 hash::BuildHasher,
38 iter::Iterator,
39 ops::{Deref, DerefMut, Range},
40 path::{Path, PathBuf},
41 str,
42 sync::Arc,
43 time::{Duration, Instant, SystemTime, UNIX_EPOCH},
44};
45use sum_tree::{Bias, FilterCursor, SumTree};
46use tree_sitter::{InputEdit, Parser, QueryCursor};
47
48pub trait File {
49 fn worktree_id(&self) -> usize;
50
51 fn entry_id(&self) -> Option<usize>;
52
53 fn set_entry_id(&mut self, entry_id: Option<usize>);
54
55 fn mtime(&self) -> SystemTime;
56
57 fn set_mtime(&mut self, mtime: SystemTime);
58
59 fn path(&self) -> &Arc<Path>;
60
61 fn set_path(&mut self, path: Arc<Path>);
62
63 fn full_path(&self, cx: &AppContext) -> PathBuf;
64
65 /// Returns the last component of this handle's absolute path. If this handle refers to the root
66 /// of its worktree, then this method will return the name of the worktree itself.
67 fn file_name<'a>(&'a self, cx: &'a AppContext) -> Option<OsString>;
68
69 fn is_deleted(&self) -> bool;
70
71 fn save(
72 &self,
73 buffer_id: u64,
74 text: Rope,
75 version: clock::Global,
76 cx: &mut MutableAppContext,
77 ) -> Task<Result<(clock::Global, SystemTime)>>;
78
79 fn buffer_updated(&self, buffer_id: u64, operation: Operation, cx: &mut MutableAppContext);
80
81 fn buffer_removed(&self, buffer_id: u64, cx: &mut MutableAppContext);
82
83 fn boxed_clone(&self) -> Box<dyn File>;
84
85 fn as_any(&self) -> &dyn Any;
86}
87
88#[derive(Clone, Default)]
89struct DeterministicState;
90
91impl BuildHasher for DeterministicState {
92 type Hasher = SeaHasher;
93
94 fn build_hasher(&self) -> Self::Hasher {
95 SeaHasher::new()
96 }
97}
98
99#[cfg(any(test, feature = "test-support"))]
100type HashMap<K, V> = std::collections::HashMap<K, V, DeterministicState>;
101
102#[cfg(any(test, feature = "test-support"))]
103type HashSet<T> = std::collections::HashSet<T, DeterministicState>;
104
105#[cfg(not(any(test, feature = "test-support")))]
106type HashMap<K, V> = std::collections::HashMap<K, V>;
107
108#[cfg(not(any(test, feature = "test-support")))]
109type HashSet<T> = std::collections::HashSet<T>;
110
111thread_local! {
112 static PARSER: RefCell<Parser> = RefCell::new(Parser::new());
113}
114
115lazy_static! {
116 static ref QUERY_CURSORS: Mutex<Vec<QueryCursor>> = Default::default();
117}
118
119// TODO - Make this configurable
120const INDENT_SIZE: u32 = 4;
121
122struct QueryCursorHandle(Option<QueryCursor>);
123
124impl QueryCursorHandle {
125 fn new() -> Self {
126 QueryCursorHandle(Some(
127 QUERY_CURSORS
128 .lock()
129 .pop()
130 .unwrap_or_else(|| QueryCursor::new()),
131 ))
132 }
133}
134
135impl Deref for QueryCursorHandle {
136 type Target = QueryCursor;
137
138 fn deref(&self) -> &Self::Target {
139 self.0.as_ref().unwrap()
140 }
141}
142
143impl DerefMut for QueryCursorHandle {
144 fn deref_mut(&mut self) -> &mut Self::Target {
145 self.0.as_mut().unwrap()
146 }
147}
148
149impl Drop for QueryCursorHandle {
150 fn drop(&mut self) {
151 let mut cursor = self.0.take().unwrap();
152 cursor.set_byte_range(0..usize::MAX);
153 cursor.set_point_range(Point::zero().into()..Point::MAX.into());
154 QUERY_CURSORS.lock().push(cursor)
155 }
156}
157
158pub struct Buffer {
159 fragments: SumTree<Fragment>,
160 visible_text: Rope,
161 deleted_text: Rope,
162 pub version: clock::Global,
163 saved_version: clock::Global,
164 saved_mtime: SystemTime,
165 last_edit: clock::Local,
166 undo_map: UndoMap,
167 history: History,
168 file: Option<Box<dyn File>>,
169 language: Option<Arc<Language>>,
170 autoindent_requests: Vec<Arc<AutoindentRequest>>,
171 pending_autoindent: Option<Task<()>>,
172 sync_parse_timeout: Duration,
173 syntax_tree: Mutex<Option<SyntaxTree>>,
174 parsing_in_background: bool,
175 parse_count: usize,
176 selections: HashMap<SelectionSetId, SelectionSet>,
177 deferred_ops: OperationQueue,
178 deferred_replicas: HashSet<ReplicaId>,
179 replica_id: ReplicaId,
180 remote_id: u64,
181 local_clock: clock::Local,
182 lamport_clock: clock::Lamport,
183 #[cfg(test)]
184 operations: Vec<Operation>,
185}
186
187#[derive(Clone, Debug, Eq, PartialEq)]
188pub struct SelectionSet {
189 pub selections: Arc<[Selection]>,
190 pub active: bool,
191}
192
193#[derive(Clone)]
194struct SyntaxTree {
195 tree: Tree,
196 version: clock::Global,
197}
198
199#[derive(Clone)]
200struct AutoindentRequest {
201 before_edit: Snapshot,
202 edited: AnchorSet,
203 inserted: Option<AnchorRangeSet>,
204}
205
206#[derive(Clone, Debug)]
207struct Transaction {
208 start: clock::Global,
209 end: clock::Global,
210 buffer_was_dirty: bool,
211 edits: Vec<clock::Local>,
212 ranges: Vec<Range<usize>>,
213 selections_before: Option<(SelectionSetId, Arc<[Selection]>)>,
214 selections_after: Option<(SelectionSetId, Arc<[Selection]>)>,
215 first_edit_at: Instant,
216 last_edit_at: Instant,
217}
218
219impl Transaction {
220 fn push_edit(&mut self, edit: &EditOperation) {
221 self.edits.push(edit.timestamp.local());
222 self.end.observe(edit.timestamp.local());
223
224 let mut other_ranges = edit.ranges.iter().peekable();
225 let mut new_ranges: Vec<Range<usize>> = Vec::new();
226 let insertion_len = edit.new_text.as_ref().map_or(0, |t| t.len());
227 let mut delta = 0;
228
229 for mut self_range in self.ranges.iter().cloned() {
230 self_range.start += delta;
231 self_range.end += delta;
232
233 while let Some(other_range) = other_ranges.peek() {
234 let mut other_range = (*other_range).clone();
235 other_range.start += delta;
236 other_range.end += delta;
237
238 if other_range.start <= self_range.end {
239 other_ranges.next().unwrap();
240 delta += insertion_len;
241
242 if other_range.end < self_range.start {
243 new_ranges.push(other_range.start..other_range.end + insertion_len);
244 self_range.start += insertion_len;
245 self_range.end += insertion_len;
246 } else {
247 self_range.start = cmp::min(self_range.start, other_range.start);
248 self_range.end = cmp::max(self_range.end, other_range.end) + insertion_len;
249 }
250 } else {
251 break;
252 }
253 }
254
255 new_ranges.push(self_range);
256 }
257
258 for other_range in other_ranges {
259 new_ranges.push(other_range.start + delta..other_range.end + delta + insertion_len);
260 delta += insertion_len;
261 }
262
263 self.ranges = new_ranges;
264 }
265}
266
267#[derive(Clone)]
268pub struct History {
269 // TODO: Turn this into a String or Rope, maybe.
270 pub base_text: Arc<str>,
271 ops: HashMap<clock::Local, EditOperation>,
272 undo_stack: Vec<Transaction>,
273 redo_stack: Vec<Transaction>,
274 transaction_depth: usize,
275 group_interval: Duration,
276}
277
278impl History {
279 pub fn new(base_text: Arc<str>) -> Self {
280 Self {
281 base_text,
282 ops: Default::default(),
283 undo_stack: Vec::new(),
284 redo_stack: Vec::new(),
285 transaction_depth: 0,
286 group_interval: Duration::from_millis(300),
287 }
288 }
289
290 fn push(&mut self, op: EditOperation) {
291 self.ops.insert(op.timestamp.local(), op);
292 }
293
294 fn start_transaction(
295 &mut self,
296 start: clock::Global,
297 buffer_was_dirty: bool,
298 selections: Option<(SelectionSetId, Arc<[Selection]>)>,
299 now: Instant,
300 ) {
301 self.transaction_depth += 1;
302 if self.transaction_depth == 1 {
303 self.undo_stack.push(Transaction {
304 start: start.clone(),
305 end: start,
306 buffer_was_dirty,
307 edits: Vec::new(),
308 ranges: Vec::new(),
309 selections_before: selections,
310 selections_after: None,
311 first_edit_at: now,
312 last_edit_at: now,
313 });
314 }
315 }
316
317 fn end_transaction(
318 &mut self,
319 selections: Option<(SelectionSetId, Arc<[Selection]>)>,
320 now: Instant,
321 ) -> Option<&Transaction> {
322 assert_ne!(self.transaction_depth, 0);
323 self.transaction_depth -= 1;
324 if self.transaction_depth == 0 {
325 if self.undo_stack.last().unwrap().ranges.is_empty() {
326 self.undo_stack.pop();
327 None
328 } else {
329 let transaction = self.undo_stack.last_mut().unwrap();
330 transaction.selections_after = selections;
331 transaction.last_edit_at = now;
332 Some(transaction)
333 }
334 } else {
335 None
336 }
337 }
338
339 fn group(&mut self) {
340 let mut new_len = self.undo_stack.len();
341 let mut transactions = self.undo_stack.iter_mut();
342
343 if let Some(mut transaction) = transactions.next_back() {
344 while let Some(prev_transaction) = transactions.next_back() {
345 if transaction.first_edit_at - prev_transaction.last_edit_at <= self.group_interval
346 && transaction.start == prev_transaction.end
347 {
348 transaction = prev_transaction;
349 new_len -= 1;
350 } else {
351 break;
352 }
353 }
354 }
355
356 let (transactions_to_keep, transactions_to_merge) = self.undo_stack.split_at_mut(new_len);
357 if let Some(last_transaction) = transactions_to_keep.last_mut() {
358 for transaction in &*transactions_to_merge {
359 for edit_id in &transaction.edits {
360 last_transaction.push_edit(&self.ops[edit_id]);
361 }
362 }
363
364 if let Some(transaction) = transactions_to_merge.last_mut() {
365 last_transaction.last_edit_at = transaction.last_edit_at;
366 last_transaction.selections_after = transaction.selections_after.take();
367 last_transaction.end = transaction.end.clone();
368 }
369 }
370
371 self.undo_stack.truncate(new_len);
372 }
373
374 fn push_undo(&mut self, edit_id: clock::Local) {
375 assert_ne!(self.transaction_depth, 0);
376 let last_transaction = self.undo_stack.last_mut().unwrap();
377 last_transaction.push_edit(&self.ops[&edit_id]);
378 }
379
380 fn pop_undo(&mut self) -> Option<&Transaction> {
381 assert_eq!(self.transaction_depth, 0);
382 if let Some(transaction) = self.undo_stack.pop() {
383 self.redo_stack.push(transaction);
384 self.redo_stack.last()
385 } else {
386 None
387 }
388 }
389
390 fn pop_redo(&mut self) -> Option<&Transaction> {
391 assert_eq!(self.transaction_depth, 0);
392 if let Some(transaction) = self.redo_stack.pop() {
393 self.undo_stack.push(transaction);
394 self.undo_stack.last()
395 } else {
396 None
397 }
398 }
399}
400
401#[derive(Clone, Default, Debug)]
402struct UndoMap(HashMap<clock::Local, Vec<(clock::Local, u32)>>);
403
404impl UndoMap {
405 fn insert(&mut self, undo: &UndoOperation) {
406 for (edit_id, count) in &undo.counts {
407 self.0.entry(*edit_id).or_default().push((undo.id, *count));
408 }
409 }
410
411 fn is_undone(&self, edit_id: clock::Local) -> bool {
412 self.undo_count(edit_id) % 2 == 1
413 }
414
415 fn was_undone(&self, edit_id: clock::Local, version: &clock::Global) -> bool {
416 let undo_count = self
417 .0
418 .get(&edit_id)
419 .unwrap_or(&Vec::new())
420 .iter()
421 .filter(|(undo_id, _)| version.observed(*undo_id))
422 .map(|(_, undo_count)| *undo_count)
423 .max()
424 .unwrap_or(0);
425 undo_count % 2 == 1
426 }
427
428 fn undo_count(&self, edit_id: clock::Local) -> u32 {
429 self.0
430 .get(&edit_id)
431 .unwrap_or(&Vec::new())
432 .iter()
433 .map(|(_, undo_count)| *undo_count)
434 .max()
435 .unwrap_or(0)
436 }
437}
438
439struct Edits<'a, F: Fn(&FragmentSummary) -> bool> {
440 visible_text: &'a Rope,
441 deleted_text: &'a Rope,
442 cursor: Option<FilterCursor<'a, F, Fragment, FragmentTextSummary>>,
443 undos: &'a UndoMap,
444 since: clock::Global,
445 old_offset: usize,
446 new_offset: usize,
447 old_point: Point,
448 new_point: Point,
449}
450
451#[derive(Clone, Debug, Default, Eq, PartialEq)]
452pub struct Edit {
453 pub old_bytes: Range<usize>,
454 pub new_bytes: Range<usize>,
455 pub old_lines: Range<Point>,
456}
457
458impl Edit {
459 pub fn delta(&self) -> isize {
460 self.inserted_bytes() as isize - self.deleted_bytes() as isize
461 }
462
463 pub fn deleted_bytes(&self) -> usize {
464 self.old_bytes.end - self.old_bytes.start
465 }
466
467 pub fn inserted_bytes(&self) -> usize {
468 self.new_bytes.end - self.new_bytes.start
469 }
470
471 pub fn deleted_lines(&self) -> Point {
472 self.old_lines.end - self.old_lines.start
473 }
474}
475
476struct Diff {
477 base_version: clock::Global,
478 new_text: Arc<str>,
479 changes: Vec<(ChangeTag, usize)>,
480}
481
482#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
483struct InsertionTimestamp {
484 replica_id: ReplicaId,
485 local: clock::Seq,
486 lamport: clock::Seq,
487}
488
489impl InsertionTimestamp {
490 fn local(&self) -> clock::Local {
491 clock::Local {
492 replica_id: self.replica_id,
493 value: self.local,
494 }
495 }
496
497 fn lamport(&self) -> clock::Lamport {
498 clock::Lamport {
499 replica_id: self.replica_id,
500 value: self.lamport,
501 }
502 }
503}
504
505#[derive(Eq, PartialEq, Clone, Debug)]
506struct Fragment {
507 timestamp: InsertionTimestamp,
508 len: usize,
509 visible: bool,
510 deletions: HashSet<clock::Local>,
511 max_undos: clock::Global,
512}
513
514#[derive(Eq, PartialEq, Clone, Debug)]
515pub struct FragmentSummary {
516 text: FragmentTextSummary,
517 max_version: clock::Global,
518 min_insertion_version: clock::Global,
519 max_insertion_version: clock::Global,
520}
521
522#[derive(Copy, Default, Clone, Debug, PartialEq, Eq)]
523struct FragmentTextSummary {
524 visible: usize,
525 deleted: usize,
526}
527
528impl<'a> sum_tree::Dimension<'a, FragmentSummary> for FragmentTextSummary {
529 fn add_summary(&mut self, summary: &'a FragmentSummary, _: &Option<clock::Global>) {
530 self.visible += summary.text.visible;
531 self.deleted += summary.text.deleted;
532 }
533}
534
535#[derive(Clone, Debug, Eq, PartialEq)]
536pub enum Operation {
537 Edit(EditOperation),
538 Undo {
539 undo: UndoOperation,
540 lamport_timestamp: clock::Lamport,
541 },
542 UpdateSelections {
543 set_id: SelectionSetId,
544 selections: Option<Arc<[Selection]>>,
545 lamport_timestamp: clock::Lamport,
546 },
547 SetActiveSelections {
548 set_id: Option<SelectionSetId>,
549 lamport_timestamp: clock::Lamport,
550 },
551 #[cfg(test)]
552 Test(clock::Lamport),
553}
554
555#[derive(Clone, Debug, Eq, PartialEq)]
556pub struct EditOperation {
557 timestamp: InsertionTimestamp,
558 version: clock::Global,
559 ranges: Vec<Range<usize>>,
560 new_text: Option<String>,
561}
562
563#[derive(Clone, Debug, Eq, PartialEq)]
564pub struct UndoOperation {
565 id: clock::Local,
566 counts: HashMap<clock::Local, u32>,
567 ranges: Vec<Range<usize>>,
568 version: clock::Global,
569}
570
571impl Buffer {
572 pub fn new<T: Into<Arc<str>>>(
573 replica_id: ReplicaId,
574 base_text: T,
575 cx: &mut ModelContext<Self>,
576 ) -> Self {
577 Self::build(
578 replica_id,
579 History::new(base_text.into()),
580 None,
581 cx.model_id() as u64,
582 None,
583 cx,
584 )
585 }
586
587 pub fn from_history(
588 replica_id: ReplicaId,
589 history: History,
590 file: Option<Box<dyn File>>,
591 language: Option<Arc<Language>>,
592 cx: &mut ModelContext<Self>,
593 ) -> Self {
594 Self::build(
595 replica_id,
596 history,
597 file,
598 cx.model_id() as u64,
599 language,
600 cx,
601 )
602 }
603
604 fn build(
605 replica_id: ReplicaId,
606 history: History,
607 file: Option<Box<dyn File>>,
608 remote_id: u64,
609 language: Option<Arc<Language>>,
610 cx: &mut ModelContext<Self>,
611 ) -> Self {
612 let saved_mtime;
613 if let Some(file) = file.as_ref() {
614 saved_mtime = file.mtime();
615 } else {
616 saved_mtime = UNIX_EPOCH;
617 }
618
619 let mut fragments = SumTree::new();
620
621 let visible_text = Rope::from(history.base_text.as_ref());
622 if visible_text.len() > 0 {
623 fragments.push(
624 Fragment {
625 timestamp: Default::default(),
626 len: visible_text.len(),
627 visible: true,
628 deletions: Default::default(),
629 max_undos: Default::default(),
630 },
631 &None,
632 );
633 }
634
635 let mut result = Self {
636 visible_text,
637 deleted_text: Rope::new(),
638 fragments,
639 version: clock::Global::new(),
640 saved_version: clock::Global::new(),
641 last_edit: clock::Local::default(),
642 undo_map: Default::default(),
643 history,
644 file,
645 syntax_tree: Mutex::new(None),
646 parsing_in_background: false,
647 parse_count: 0,
648 sync_parse_timeout: Duration::from_millis(1),
649 autoindent_requests: Default::default(),
650 pending_autoindent: Default::default(),
651 language,
652 saved_mtime,
653 selections: HashMap::default(),
654 deferred_ops: OperationQueue::new(),
655 deferred_replicas: HashSet::default(),
656 replica_id,
657 remote_id,
658 local_clock: clock::Local::new(replica_id),
659 lamport_clock: clock::Lamport::new(replica_id),
660
661 #[cfg(test)]
662 operations: Default::default(),
663 };
664 result.reparse(cx);
665 result
666 }
667
668 pub fn replica_id(&self) -> ReplicaId {
669 self.local_clock.replica_id
670 }
671
672 pub fn snapshot(&self) -> Snapshot {
673 Snapshot {
674 visible_text: self.visible_text.clone(),
675 fragments: self.fragments.clone(),
676 version: self.version.clone(),
677 tree: self.syntax_tree(),
678 is_parsing: self.parsing_in_background,
679 language: self.language.clone(),
680 query_cursor: QueryCursorHandle::new(),
681 }
682 }
683
684 pub fn from_proto(
685 replica_id: ReplicaId,
686 message: proto::Buffer,
687 file: Option<Box<dyn File>>,
688 language: Option<Arc<Language>>,
689 cx: &mut ModelContext<Self>,
690 ) -> Result<Self> {
691 let mut buffer = Buffer::build(
692 replica_id,
693 History::new(message.content.into()),
694 file,
695 message.id,
696 language,
697 cx,
698 );
699 let ops = message
700 .history
701 .into_iter()
702 .map(|op| Operation::Edit(op.into()));
703 buffer.apply_ops(ops, cx)?;
704 buffer.selections = message
705 .selections
706 .into_iter()
707 .map(|set| {
708 let set_id = clock::Lamport {
709 replica_id: set.replica_id as ReplicaId,
710 value: set.local_timestamp,
711 };
712 let selections: Vec<Selection> = set
713 .selections
714 .into_iter()
715 .map(TryFrom::try_from)
716 .collect::<Result<_, _>>()?;
717 let set = SelectionSet {
718 selections: Arc::from(selections),
719 active: set.is_active,
720 };
721 Result::<_, anyhow::Error>::Ok((set_id, set))
722 })
723 .collect::<Result<_, _>>()?;
724 Ok(buffer)
725 }
726
727 pub fn to_proto(&self, cx: &mut ModelContext<Self>) -> proto::Buffer {
728 let ops = self.history.ops.values().map(Into::into).collect();
729 proto::Buffer {
730 id: cx.model_id() as u64,
731 content: self.history.base_text.to_string(),
732 history: ops,
733 selections: self
734 .selections
735 .iter()
736 .map(|(set_id, set)| proto::SelectionSetSnapshot {
737 replica_id: set_id.replica_id as u32,
738 local_timestamp: set_id.value,
739 selections: set.selections.iter().map(Into::into).collect(),
740 is_active: set.active,
741 })
742 .collect(),
743 }
744 }
745
746 pub fn file(&self) -> Option<&dyn File> {
747 self.file.as_deref()
748 }
749
750 pub fn file_mut(&mut self) -> Option<&mut dyn File> {
751 self.file.as_mut().map(|f| f.deref_mut() as &mut dyn File)
752 }
753
754 pub fn save(
755 &mut self,
756 cx: &mut ModelContext<Self>,
757 ) -> Result<Task<Result<(clock::Global, SystemTime)>>> {
758 let file = self
759 .file
760 .as_ref()
761 .ok_or_else(|| anyhow!("buffer has no file"))?;
762 let text = self.visible_text.clone();
763 let version = self.version.clone();
764 let save = file.save(self.remote_id, text, version, cx.as_mut());
765 Ok(cx.spawn(|this, mut cx| async move {
766 let (version, mtime) = save.await?;
767 this.update(&mut cx, |this, cx| {
768 this.did_save(version.clone(), mtime, None, cx);
769 });
770 Ok((version, mtime))
771 }))
772 }
773
774 pub fn as_rope(&self) -> &Rope {
775 &self.visible_text
776 }
777
778 pub fn set_language(&mut self, language: Option<Arc<Language>>, cx: &mut ModelContext<Self>) {
779 self.language = language;
780 self.reparse(cx);
781 }
782
783 pub fn did_save(
784 &mut self,
785 version: clock::Global,
786 mtime: SystemTime,
787 new_file: Option<Box<dyn File>>,
788 cx: &mut ModelContext<Self>,
789 ) {
790 self.saved_mtime = mtime;
791 self.saved_version = version;
792 if let Some(new_file) = new_file {
793 self.file = Some(new_file);
794 }
795 cx.emit(Event::Saved);
796 }
797
798 pub fn file_updated(
799 &mut self,
800 path: Arc<Path>,
801 mtime: SystemTime,
802 new_text: Option<String>,
803 cx: &mut ModelContext<Self>,
804 ) {
805 let file = self.file.as_mut().unwrap();
806 let mut changed = false;
807 if path != *file.path() {
808 file.set_path(path);
809 changed = true;
810 }
811
812 if mtime != file.mtime() {
813 file.set_mtime(mtime);
814 changed = true;
815 if let Some(new_text) = new_text {
816 if self.version == self.saved_version {
817 cx.spawn(|this, mut cx| async move {
818 let diff = this
819 .read_with(&cx, |this, cx| this.diff(new_text.into(), cx))
820 .await;
821 this.update(&mut cx, |this, cx| {
822 if this.apply_diff(diff, cx) {
823 this.saved_version = this.version.clone();
824 this.saved_mtime = mtime;
825 cx.emit(Event::Reloaded);
826 }
827 });
828 })
829 .detach();
830 }
831 }
832 }
833
834 if changed {
835 cx.emit(Event::FileHandleChanged);
836 }
837 }
838
839 pub fn file_deleted(&mut self, cx: &mut ModelContext<Self>) {
840 if self.version == self.saved_version {
841 cx.emit(Event::Dirtied);
842 }
843 cx.emit(Event::FileHandleChanged);
844 }
845
846 pub fn close(&mut self, cx: &mut ModelContext<Self>) {
847 cx.emit(Event::Closed);
848 }
849
850 pub fn language(&self) -> Option<&Arc<Language>> {
851 self.language.as_ref()
852 }
853
854 pub fn parse_count(&self) -> usize {
855 self.parse_count
856 }
857
858 fn syntax_tree(&self) -> Option<Tree> {
859 if let Some(syntax_tree) = self.syntax_tree.lock().as_mut() {
860 self.interpolate_tree(syntax_tree);
861 Some(syntax_tree.tree.clone())
862 } else {
863 None
864 }
865 }
866
867 #[cfg(any(test, feature = "test-support"))]
868 pub fn is_parsing(&self) -> bool {
869 self.parsing_in_background
870 }
871
872 #[cfg(test)]
873 pub fn set_sync_parse_timeout(&mut self, timeout: Duration) {
874 self.sync_parse_timeout = timeout;
875 }
876
877 fn reparse(&mut self, cx: &mut ModelContext<Self>) -> bool {
878 if self.parsing_in_background {
879 return false;
880 }
881
882 if let Some(language) = self.language.clone() {
883 let old_tree = self.syntax_tree();
884 let text = self.visible_text.clone();
885 let parsed_version = self.version();
886 let parse_task = cx.background().spawn({
887 let language = language.clone();
888 async move { Self::parse_text(&text, old_tree, &language) }
889 });
890
891 match cx
892 .background()
893 .block_with_timeout(self.sync_parse_timeout, parse_task)
894 {
895 Ok(new_tree) => {
896 self.did_finish_parsing(new_tree, parsed_version, cx);
897 return true;
898 }
899 Err(parse_task) => {
900 self.parsing_in_background = true;
901 cx.spawn(move |this, mut cx| async move {
902 let new_tree = parse_task.await;
903 this.update(&mut cx, move |this, cx| {
904 let language_changed =
905 this.language.as_ref().map_or(true, |curr_language| {
906 !Arc::ptr_eq(curr_language, &language)
907 });
908 let parse_again = this.version > parsed_version || language_changed;
909 this.parsing_in_background = false;
910 this.did_finish_parsing(new_tree, parsed_version, cx);
911
912 if parse_again && this.reparse(cx) {
913 return;
914 }
915 });
916 })
917 .detach();
918 }
919 }
920 }
921 false
922 }
923
924 fn parse_text(text: &Rope, old_tree: Option<Tree>, language: &Language) -> Tree {
925 PARSER.with(|parser| {
926 let mut parser = parser.borrow_mut();
927 parser
928 .set_language(language.grammar)
929 .expect("incompatible grammar");
930 let mut chunks = text.chunks_in_range(0..text.len());
931 let tree = parser
932 .parse_with(
933 &mut move |offset, _| {
934 chunks.seek(offset);
935 chunks.next().unwrap_or("").as_bytes()
936 },
937 old_tree.as_ref(),
938 )
939 .unwrap();
940 tree
941 })
942 }
943
944 fn interpolate_tree(&self, tree: &mut SyntaxTree) {
945 let mut delta = 0_isize;
946 for edit in self.edits_since(tree.version.clone()) {
947 let start_offset = (edit.old_bytes.start as isize + delta) as usize;
948 let start_point = self.visible_text.to_point(start_offset);
949 tree.tree.edit(&InputEdit {
950 start_byte: start_offset,
951 old_end_byte: start_offset + edit.deleted_bytes(),
952 new_end_byte: start_offset + edit.inserted_bytes(),
953 start_position: start_point.into(),
954 old_end_position: (start_point + edit.deleted_lines()).into(),
955 new_end_position: self
956 .visible_text
957 .to_point(start_offset + edit.inserted_bytes())
958 .into(),
959 });
960 delta += edit.inserted_bytes() as isize - edit.deleted_bytes() as isize;
961 }
962 tree.version = self.version();
963 }
964
965 fn did_finish_parsing(
966 &mut self,
967 tree: Tree,
968 version: clock::Global,
969 cx: &mut ModelContext<Self>,
970 ) {
971 self.parse_count += 1;
972 *self.syntax_tree.lock() = Some(SyntaxTree { tree, version });
973 self.request_autoindent(cx);
974 cx.emit(Event::Reparsed);
975 cx.notify();
976 }
977
978 fn request_autoindent(&mut self, cx: &mut ModelContext<Self>) {
979 if let Some(indent_columns) = self.compute_autoindents() {
980 let indent_columns = cx.background().spawn(indent_columns);
981 match cx
982 .background()
983 .block_with_timeout(Duration::from_micros(500), indent_columns)
984 {
985 Ok(indent_columns) => {
986 log::info!("finished synchronously {:?}", indent_columns);
987 self.autoindent_requests.clear();
988 self.start_transaction(None).unwrap();
989 for (row, indent_column) in indent_columns {
990 self.set_indent_column_for_line(row, indent_column, cx);
991 }
992 self.end_transaction(None, cx).unwrap();
993 }
994 Err(indent_columns) => {
995 self.pending_autoindent = Some(cx.spawn(|this, mut cx| async move {
996 let indent_columns = indent_columns.await;
997 log::info!("finished ASYNC, {:?}", indent_columns);
998 this.update(&mut cx, |this, cx| {
999 this.autoindent_requests.clear();
1000 this.start_transaction(None).unwrap();
1001 for (row, indent_column) in indent_columns {
1002 this.set_indent_column_for_line(row, indent_column, cx);
1003 }
1004 this.end_transaction(None, cx).unwrap();
1005 });
1006 }));
1007 }
1008 }
1009 }
1010 }
1011
1012 fn compute_autoindents(&self) -> Option<impl Future<Output = BTreeMap<u32, u32>>> {
1013 let snapshot = self.snapshot();
1014 if snapshot.language.is_none()
1015 || snapshot.tree.is_none()
1016 || self.autoindent_requests.is_empty()
1017 {
1018 return None;
1019 }
1020
1021 let autoindent_requests = self.autoindent_requests.clone();
1022 Some(async move {
1023 let mut indent_columns = BTreeMap::new();
1024 for request in autoindent_requests {
1025 let old_to_new_rows = request
1026 .edited
1027 .to_points(&request.before_edit)
1028 .map(|point| point.row)
1029 .zip(request.edited.to_points(&snapshot).map(|point| point.row))
1030 .collect::<BTreeMap<u32, u32>>();
1031
1032 let mut old_suggestions = HashMap::default();
1033 let old_edited_ranges = contiguous_ranges(old_to_new_rows.keys().copied());
1034 for old_edited_range in old_edited_ranges {
1035 let suggestions = request
1036 .before_edit
1037 .suggest_autoindents(old_edited_range.clone())
1038 .into_iter()
1039 .flatten();
1040 for (old_row, suggestion) in old_edited_range.zip(suggestions) {
1041 let indentation_basis = old_to_new_rows
1042 .get(&suggestion.basis_row)
1043 .and_then(|from_row| old_suggestions.get(from_row).copied())
1044 .unwrap_or_else(|| {
1045 request
1046 .before_edit
1047 .indent_column_for_line(suggestion.basis_row)
1048 });
1049 let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
1050 old_suggestions.insert(
1051 *old_to_new_rows.get(&old_row).unwrap(),
1052 indentation_basis + delta,
1053 );
1054 }
1055 }
1056
1057 // At this point, old_suggestions contains the suggested indentation for all edited lines with respect to the state of the
1058 // buffer before the edit, but keyed by the row for these lines after the edits were applied.
1059 let new_edited_row_ranges = contiguous_ranges(old_to_new_rows.values().copied());
1060 for new_edited_row_range in new_edited_row_ranges {
1061 let suggestions = snapshot
1062 .suggest_autoindents(new_edited_row_range.clone())
1063 .into_iter()
1064 .flatten();
1065 for (new_row, suggestion) in new_edited_row_range.zip(suggestions) {
1066 let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
1067 let new_indentation = indent_columns
1068 .get(&suggestion.basis_row)
1069 .copied()
1070 .unwrap_or_else(|| {
1071 snapshot.indent_column_for_line(suggestion.basis_row)
1072 })
1073 + delta;
1074 if old_suggestions
1075 .get(&new_row)
1076 .map_or(true, |old_indentation| new_indentation != *old_indentation)
1077 {
1078 indent_columns.insert(new_row, new_indentation);
1079 }
1080 }
1081 }
1082
1083 if let Some(inserted) = request.inserted.as_ref() {
1084 let inserted_row_ranges = contiguous_ranges(
1085 inserted
1086 .to_point_ranges(&snapshot)
1087 .flat_map(|range| range.start.row..range.end.row + 1),
1088 );
1089 for inserted_row_range in inserted_row_ranges {
1090 let suggestions = snapshot
1091 .suggest_autoindents(inserted_row_range.clone())
1092 .into_iter()
1093 .flatten();
1094 for (row, suggestion) in inserted_row_range.zip(suggestions) {
1095 let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
1096 let new_indentation = indent_columns
1097 .get(&suggestion.basis_row)
1098 .copied()
1099 .unwrap_or_else(|| {
1100 snapshot.indent_column_for_line(suggestion.basis_row)
1101 })
1102 + delta;
1103 indent_columns.insert(row, new_indentation);
1104 }
1105 }
1106 }
1107 }
1108 indent_columns
1109 })
1110 }
1111
1112 pub fn indent_column_for_line(&self, row: u32) -> u32 {
1113 self.content().indent_column_for_line(row)
1114 }
1115
1116 fn set_indent_column_for_line(&mut self, row: u32, column: u32, cx: &mut ModelContext<Self>) {
1117 let current_column = self.indent_column_for_line(row);
1118 if column > current_column {
1119 let offset = self.visible_text.to_offset(Point::new(row, 0));
1120
1121 // TODO: do this differently. By replacing the preceding newline,
1122 // we force the new indentation to come before any left-biased anchors
1123 // on the line.
1124 let delta = (column - current_column) as usize;
1125 if offset > 0 {
1126 let mut prefix = String::with_capacity(1 + delta);
1127 prefix.push('\n');
1128 prefix.extend(std::iter::repeat(' ').take(delta));
1129 self.edit([(offset - 1)..offset], prefix, cx);
1130 } else {
1131 self.edit(
1132 [offset..offset],
1133 std::iter::repeat(' ').take(delta).collect::<String>(),
1134 cx,
1135 );
1136 }
1137 } else if column < current_column {
1138 self.edit(
1139 [Point::new(row, 0)..Point::new(row, current_column - column)],
1140 "",
1141 cx,
1142 );
1143 }
1144 }
1145
1146 pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
1147 if let Some(tree) = self.syntax_tree() {
1148 let root = tree.root_node();
1149 let range = range.start.to_offset(self)..range.end.to_offset(self);
1150 let mut node = root.descendant_for_byte_range(range.start, range.end);
1151 while node.map_or(false, |n| n.byte_range() == range) {
1152 node = node.unwrap().parent();
1153 }
1154 node.map(|n| n.byte_range())
1155 } else {
1156 None
1157 }
1158 }
1159
1160 pub fn enclosing_bracket_ranges<T: ToOffset>(
1161 &self,
1162 range: Range<T>,
1163 ) -> Option<(Range<usize>, Range<usize>)> {
1164 let (lang, tree) = self.language.as_ref().zip(self.syntax_tree())?;
1165 let open_capture_ix = lang.brackets_query.capture_index_for_name("open")?;
1166 let close_capture_ix = lang.brackets_query.capture_index_for_name("close")?;
1167
1168 // Find bracket pairs that *inclusively* contain the given range.
1169 let range = range.start.to_offset(self).saturating_sub(1)..range.end.to_offset(self) + 1;
1170 let mut cursor = QueryCursorHandle::new();
1171 let matches = cursor.set_byte_range(range).matches(
1172 &lang.brackets_query,
1173 tree.root_node(),
1174 TextProvider(&self.visible_text),
1175 );
1176
1177 // Get the ranges of the innermost pair of brackets.
1178 matches
1179 .filter_map(|mat| {
1180 let open = mat.nodes_for_capture_index(open_capture_ix).next()?;
1181 let close = mat.nodes_for_capture_index(close_capture_ix).next()?;
1182 Some((open.byte_range(), close.byte_range()))
1183 })
1184 .min_by_key(|(open_range, close_range)| close_range.end - open_range.start)
1185 }
1186
1187 fn diff(&self, new_text: Arc<str>, cx: &AppContext) -> Task<Diff> {
1188 // TODO: it would be nice to not allocate here.
1189 let old_text = self.text();
1190 let base_version = self.version();
1191 cx.background().spawn(async move {
1192 let changes = TextDiff::from_lines(old_text.as_str(), new_text.as_ref())
1193 .iter_all_changes()
1194 .map(|c| (c.tag(), c.value().len()))
1195 .collect::<Vec<_>>();
1196 Diff {
1197 base_version,
1198 new_text,
1199 changes,
1200 }
1201 })
1202 }
1203
1204 pub fn set_text_from_disk(&self, new_text: Arc<str>, cx: &mut ModelContext<Self>) -> Task<()> {
1205 cx.spawn(|this, mut cx| async move {
1206 let diff = this
1207 .read_with(&cx, |this, cx| this.diff(new_text, cx))
1208 .await;
1209
1210 this.update(&mut cx, |this, cx| {
1211 if this.apply_diff(diff, cx) {
1212 this.saved_version = this.version.clone();
1213 }
1214 });
1215 })
1216 }
1217
1218 fn apply_diff(&mut self, diff: Diff, cx: &mut ModelContext<Self>) -> bool {
1219 if self.version == diff.base_version {
1220 self.start_transaction(None).unwrap();
1221 let mut offset = 0;
1222 for (tag, len) in diff.changes {
1223 let range = offset..(offset + len);
1224 match tag {
1225 ChangeTag::Equal => offset += len,
1226 ChangeTag::Delete => self.edit(Some(range), "", cx),
1227 ChangeTag::Insert => {
1228 self.edit(Some(offset..offset), &diff.new_text[range], cx);
1229 offset += len;
1230 }
1231 }
1232 }
1233 self.end_transaction(None, cx).unwrap();
1234 true
1235 } else {
1236 false
1237 }
1238 }
1239
1240 pub fn is_dirty(&self) -> bool {
1241 self.version > self.saved_version
1242 || self.file.as_ref().map_or(false, |file| file.is_deleted())
1243 }
1244
1245 pub fn has_conflict(&self) -> bool {
1246 self.version > self.saved_version
1247 && self
1248 .file
1249 .as_ref()
1250 .map_or(false, |file| file.mtime() > self.saved_mtime)
1251 }
1252
1253 pub fn remote_id(&self) -> u64 {
1254 self.remote_id
1255 }
1256
1257 pub fn version(&self) -> clock::Global {
1258 self.version.clone()
1259 }
1260
1261 pub fn text_summary(&self) -> TextSummary {
1262 self.visible_text.summary()
1263 }
1264
1265 pub fn len(&self) -> usize {
1266 self.content().len()
1267 }
1268
1269 pub fn line_len(&self, row: u32) -> u32 {
1270 self.content().line_len(row)
1271 }
1272
1273 pub fn max_point(&self) -> Point {
1274 self.visible_text.max_point()
1275 }
1276
1277 pub fn row_count(&self) -> u32 {
1278 self.max_point().row + 1
1279 }
1280
1281 pub fn text(&self) -> String {
1282 self.text_for_range(0..self.len()).collect()
1283 }
1284
1285 pub fn text_for_range<'a, T: ToOffset>(&'a self, range: Range<T>) -> Chunks<'a> {
1286 self.content().text_for_range(range)
1287 }
1288
1289 pub fn chars(&self) -> impl Iterator<Item = char> + '_ {
1290 self.chars_at(0)
1291 }
1292
1293 pub fn chars_at<'a, T: 'a + ToOffset>(
1294 &'a self,
1295 position: T,
1296 ) -> impl Iterator<Item = char> + 'a {
1297 self.content().chars_at(position)
1298 }
1299
1300 pub fn chars_for_range<T: ToOffset>(&self, range: Range<T>) -> impl Iterator<Item = char> + '_ {
1301 self.text_for_range(range).flat_map(str::chars)
1302 }
1303
1304 pub fn bytes_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = u8> + '_ {
1305 let offset = position.to_offset(self);
1306 self.visible_text.bytes_at(offset)
1307 }
1308
1309 pub fn contains_str_at<T>(&self, position: T, needle: &str) -> bool
1310 where
1311 T: ToOffset,
1312 {
1313 let position = position.to_offset(self);
1314 position == self.clip_offset(position, Bias::Left)
1315 && self
1316 .bytes_at(position)
1317 .take(needle.len())
1318 .eq(needle.bytes())
1319 }
1320
1321 pub fn edits_since<'a>(&'a self, since: clock::Global) -> impl 'a + Iterator<Item = Edit> {
1322 let since_2 = since.clone();
1323 let cursor = if since == self.version {
1324 None
1325 } else {
1326 Some(self.fragments.filter(
1327 move |summary| summary.max_version.changed_since(&since_2),
1328 &None,
1329 ))
1330 };
1331
1332 Edits {
1333 visible_text: &self.visible_text,
1334 deleted_text: &self.deleted_text,
1335 cursor,
1336 undos: &self.undo_map,
1337 since,
1338 old_offset: 0,
1339 new_offset: 0,
1340 old_point: Point::zero(),
1341 new_point: Point::zero(),
1342 }
1343 }
1344
1345 pub fn deferred_ops_len(&self) -> usize {
1346 self.deferred_ops.len()
1347 }
1348
1349 pub fn start_transaction(&mut self, set_id: Option<SelectionSetId>) -> Result<()> {
1350 self.start_transaction_at(set_id, Instant::now())
1351 }
1352
1353 fn start_transaction_at(&mut self, set_id: Option<SelectionSetId>, now: Instant) -> Result<()> {
1354 let selections = if let Some(set_id) = set_id {
1355 let set = self
1356 .selections
1357 .get(&set_id)
1358 .ok_or_else(|| anyhow!("invalid selection set {:?}", set_id))?;
1359 Some((set_id, set.selections.clone()))
1360 } else {
1361 None
1362 };
1363 self.history
1364 .start_transaction(self.version.clone(), self.is_dirty(), selections, now);
1365 Ok(())
1366 }
1367
1368 pub fn end_transaction(
1369 &mut self,
1370 set_id: Option<SelectionSetId>,
1371 cx: &mut ModelContext<Self>,
1372 ) -> Result<()> {
1373 self.end_transaction_at(set_id, Instant::now(), cx)
1374 }
1375
1376 fn end_transaction_at(
1377 &mut self,
1378 set_id: Option<SelectionSetId>,
1379 now: Instant,
1380 cx: &mut ModelContext<Self>,
1381 ) -> Result<()> {
1382 let selections = if let Some(set_id) = set_id {
1383 let set = self
1384 .selections
1385 .get(&set_id)
1386 .ok_or_else(|| anyhow!("invalid selection set {:?}", set_id))?;
1387 Some((set_id, set.selections.clone()))
1388 } else {
1389 None
1390 };
1391
1392 if let Some(transaction) = self.history.end_transaction(selections, now) {
1393 let since = transaction.start.clone();
1394 let was_dirty = transaction.buffer_was_dirty;
1395 self.history.group();
1396
1397 cx.notify();
1398 if self.edits_since(since).next().is_some() {
1399 self.did_edit(was_dirty, cx);
1400 self.reparse(cx);
1401 }
1402 }
1403
1404 Ok(())
1405 }
1406
1407 pub fn edit<I, S, T>(&mut self, ranges_iter: I, new_text: T, cx: &mut ModelContext<Self>)
1408 where
1409 I: IntoIterator<Item = Range<S>>,
1410 S: ToOffset,
1411 T: Into<String>,
1412 {
1413 self.edit_internal(ranges_iter, new_text, false, cx)
1414 }
1415
1416 pub fn edit_with_autoindent<I, S, T>(
1417 &mut self,
1418 ranges_iter: I,
1419 new_text: T,
1420 cx: &mut ModelContext<Self>,
1421 ) where
1422 I: IntoIterator<Item = Range<S>>,
1423 S: ToOffset,
1424 T: Into<String>,
1425 {
1426 self.edit_internal(ranges_iter, new_text, true, cx)
1427 }
1428
1429 pub fn edit_internal<I, S, T>(
1430 &mut self,
1431 ranges_iter: I,
1432 new_text: T,
1433 autoindent: bool,
1434 cx: &mut ModelContext<Self>,
1435 ) where
1436 I: IntoIterator<Item = Range<S>>,
1437 S: ToOffset,
1438 T: Into<String>,
1439 {
1440 let new_text = new_text.into();
1441
1442 // Skip invalid ranges and coalesce contiguous ones.
1443 let mut ranges: Vec<Range<usize>> = Vec::new();
1444 for range in ranges_iter {
1445 let range = range.start.to_offset(&*self)..range.end.to_offset(&*self);
1446 if !new_text.is_empty() || !range.is_empty() {
1447 if let Some(prev_range) = ranges.last_mut() {
1448 if prev_range.end >= range.start {
1449 prev_range.end = cmp::max(prev_range.end, range.end);
1450 } else {
1451 ranges.push(range);
1452 }
1453 } else {
1454 ranges.push(range);
1455 }
1456 }
1457 }
1458 if ranges.is_empty() {
1459 return;
1460 }
1461
1462 self.pending_autoindent.take();
1463 let autoindent_request = if autoindent && self.language.is_some() {
1464 let before_edit = self.snapshot();
1465 let edited = self.content().anchor_set(ranges.iter().filter_map(|range| {
1466 let start = range.start.to_point(&*self);
1467 if new_text.starts_with('\n') && start.column == self.line_len(start.row) {
1468 None
1469 } else {
1470 Some((range.start, Bias::Left))
1471 }
1472 }));
1473 Some((before_edit, edited))
1474 } else {
1475 None
1476 };
1477
1478 let first_newline_ix = new_text.find('\n');
1479 let new_text_len = new_text.len();
1480 let new_text = if new_text_len > 0 {
1481 Some(new_text)
1482 } else {
1483 None
1484 };
1485
1486 self.start_transaction(None).unwrap();
1487 let timestamp = InsertionTimestamp {
1488 replica_id: self.replica_id,
1489 local: self.local_clock.tick().value,
1490 lamport: self.lamport_clock.tick().value,
1491 };
1492 let edit = self.apply_local_edit(&ranges, new_text, timestamp);
1493
1494 self.history.push(edit.clone());
1495 self.history.push_undo(edit.timestamp.local());
1496 self.last_edit = edit.timestamp.local();
1497 self.version.observe(edit.timestamp.local());
1498
1499 if let Some((before_edit, edited)) = autoindent_request {
1500 let mut inserted = None;
1501 if let Some(first_newline_ix) = first_newline_ix {
1502 let mut delta = 0isize;
1503 inserted = Some(self.content().anchor_range_set(ranges.iter().map(|range| {
1504 let start = (delta + range.start as isize) as usize + first_newline_ix + 1;
1505 let end = (delta + range.start as isize) as usize + new_text_len;
1506 delta += (range.end as isize - range.start as isize) + new_text_len as isize;
1507 (start, Bias::Left)..(end, Bias::Right)
1508 })));
1509 }
1510
1511 self.autoindent_requests.push(Arc::new(AutoindentRequest {
1512 before_edit,
1513 edited,
1514 inserted,
1515 }));
1516 }
1517
1518 self.end_transaction(None, cx).unwrap();
1519 self.send_operation(Operation::Edit(edit), cx);
1520 }
1521
1522 fn did_edit(&self, was_dirty: bool, cx: &mut ModelContext<Self>) {
1523 cx.emit(Event::Edited);
1524 if !was_dirty {
1525 cx.emit(Event::Dirtied);
1526 }
1527 }
1528
1529 pub fn add_selection_set(
1530 &mut self,
1531 selections: impl Into<Arc<[Selection]>>,
1532 cx: &mut ModelContext<Self>,
1533 ) -> SelectionSetId {
1534 let selections = selections.into();
1535 let lamport_timestamp = self.lamport_clock.tick();
1536 self.selections.insert(
1537 lamport_timestamp,
1538 SelectionSet {
1539 selections: selections.clone(),
1540 active: false,
1541 },
1542 );
1543 cx.notify();
1544
1545 self.send_operation(
1546 Operation::UpdateSelections {
1547 set_id: lamport_timestamp,
1548 selections: Some(selections),
1549 lamport_timestamp,
1550 },
1551 cx,
1552 );
1553
1554 lamport_timestamp
1555 }
1556
1557 pub fn update_selection_set(
1558 &mut self,
1559 set_id: SelectionSetId,
1560 selections: impl Into<Arc<[Selection]>>,
1561 cx: &mut ModelContext<Self>,
1562 ) -> Result<()> {
1563 let selections = selections.into();
1564 let set = self
1565 .selections
1566 .get_mut(&set_id)
1567 .ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))?;
1568 set.selections = selections.clone();
1569 let lamport_timestamp = self.lamport_clock.tick();
1570 cx.notify();
1571 self.send_operation(
1572 Operation::UpdateSelections {
1573 set_id,
1574 selections: Some(selections),
1575 lamport_timestamp,
1576 },
1577 cx,
1578 );
1579 Ok(())
1580 }
1581
1582 pub fn set_active_selection_set(
1583 &mut self,
1584 set_id: Option<SelectionSetId>,
1585 cx: &mut ModelContext<Self>,
1586 ) -> Result<()> {
1587 if let Some(set_id) = set_id {
1588 assert_eq!(set_id.replica_id, self.replica_id());
1589 }
1590
1591 for (id, set) in &mut self.selections {
1592 if id.replica_id == self.local_clock.replica_id {
1593 if Some(*id) == set_id {
1594 set.active = true;
1595 } else {
1596 set.active = false;
1597 }
1598 }
1599 }
1600
1601 let lamport_timestamp = self.lamport_clock.tick();
1602 self.send_operation(
1603 Operation::SetActiveSelections {
1604 set_id,
1605 lamport_timestamp,
1606 },
1607 cx,
1608 );
1609 Ok(())
1610 }
1611
1612 pub fn remove_selection_set(
1613 &mut self,
1614 set_id: SelectionSetId,
1615 cx: &mut ModelContext<Self>,
1616 ) -> Result<()> {
1617 self.selections
1618 .remove(&set_id)
1619 .ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))?;
1620 let lamport_timestamp = self.lamport_clock.tick();
1621 cx.notify();
1622 self.send_operation(
1623 Operation::UpdateSelections {
1624 set_id,
1625 selections: None,
1626 lamport_timestamp,
1627 },
1628 cx,
1629 );
1630 Ok(())
1631 }
1632
1633 pub fn selection_set(&self, set_id: SelectionSetId) -> Result<&SelectionSet> {
1634 self.selections
1635 .get(&set_id)
1636 .ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))
1637 }
1638
1639 pub fn selection_sets(&self) -> impl Iterator<Item = (&SelectionSetId, &SelectionSet)> {
1640 self.selections.iter()
1641 }
1642
1643 pub fn apply_ops<I: IntoIterator<Item = Operation>>(
1644 &mut self,
1645 ops: I,
1646 cx: &mut ModelContext<Self>,
1647 ) -> Result<()> {
1648 self.pending_autoindent.take();
1649
1650 let was_dirty = self.is_dirty();
1651 let old_version = self.version.clone();
1652
1653 let mut deferred_ops = Vec::new();
1654 for op in ops {
1655 if self.can_apply_op(&op) {
1656 self.apply_op(op)?;
1657 } else {
1658 self.deferred_replicas.insert(op.replica_id());
1659 deferred_ops.push(op);
1660 }
1661 }
1662 self.deferred_ops.insert(deferred_ops);
1663 self.flush_deferred_ops()?;
1664
1665 cx.notify();
1666 if self.edits_since(old_version).next().is_some() {
1667 self.did_edit(was_dirty, cx);
1668 self.reparse(cx);
1669 }
1670
1671 Ok(())
1672 }
1673
1674 fn apply_op(&mut self, op: Operation) -> Result<()> {
1675 match op {
1676 Operation::Edit(edit) => {
1677 if !self.version.observed(edit.timestamp.local()) {
1678 self.apply_remote_edit(
1679 &edit.version,
1680 &edit.ranges,
1681 edit.new_text.as_deref(),
1682 edit.timestamp,
1683 );
1684 self.version.observe(edit.timestamp.local());
1685 self.history.push(edit);
1686 }
1687 }
1688 Operation::Undo {
1689 undo,
1690 lamport_timestamp,
1691 } => {
1692 if !self.version.observed(undo.id) {
1693 self.apply_undo(&undo)?;
1694 self.version.observe(undo.id);
1695 self.lamport_clock.observe(lamport_timestamp);
1696 }
1697 }
1698 Operation::UpdateSelections {
1699 set_id,
1700 selections,
1701 lamport_timestamp,
1702 } => {
1703 if let Some(selections) = selections {
1704 if let Some(set) = self.selections.get_mut(&set_id) {
1705 set.selections = selections;
1706 } else {
1707 self.selections.insert(
1708 set_id,
1709 SelectionSet {
1710 selections,
1711 active: false,
1712 },
1713 );
1714 }
1715 } else {
1716 self.selections.remove(&set_id);
1717 }
1718 self.lamport_clock.observe(lamport_timestamp);
1719 }
1720 Operation::SetActiveSelections {
1721 set_id,
1722 lamport_timestamp,
1723 } => {
1724 for (id, set) in &mut self.selections {
1725 if id.replica_id == lamport_timestamp.replica_id {
1726 if Some(*id) == set_id {
1727 set.active = true;
1728 } else {
1729 set.active = false;
1730 }
1731 }
1732 }
1733 self.lamport_clock.observe(lamport_timestamp);
1734 }
1735 #[cfg(test)]
1736 Operation::Test(_) => {}
1737 }
1738 Ok(())
1739 }
1740
1741 fn apply_remote_edit(
1742 &mut self,
1743 version: &clock::Global,
1744 ranges: &[Range<usize>],
1745 new_text: Option<&str>,
1746 timestamp: InsertionTimestamp,
1747 ) {
1748 if ranges.is_empty() {
1749 return;
1750 }
1751
1752 let cx = Some(version.clone());
1753 let mut new_ropes =
1754 RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
1755 let mut old_fragments = self.fragments.cursor::<VersionedOffset>();
1756 let mut new_fragments =
1757 old_fragments.slice(&VersionedOffset::Offset(ranges[0].start), Bias::Left, &cx);
1758 new_ropes.push_tree(new_fragments.summary().text);
1759
1760 let mut fragment_start = old_fragments.start().offset();
1761 for range in ranges {
1762 let fragment_end = old_fragments.end(&cx).offset();
1763
1764 // If the current fragment ends before this range, then jump ahead to the first fragment
1765 // that extends past the start of this range, reusing any intervening fragments.
1766 if fragment_end < range.start {
1767 // If the current fragment has been partially consumed, then consume the rest of it
1768 // and advance to the next fragment before slicing.
1769 if fragment_start > old_fragments.start().offset() {
1770 if fragment_end > fragment_start {
1771 let mut suffix = old_fragments.item().unwrap().clone();
1772 suffix.len = fragment_end - fragment_start;
1773 new_ropes.push_fragment(&suffix, suffix.visible);
1774 new_fragments.push(suffix, &None);
1775 }
1776 old_fragments.next(&cx);
1777 }
1778
1779 let slice =
1780 old_fragments.slice(&VersionedOffset::Offset(range.start), Bias::Left, &cx);
1781 new_ropes.push_tree(slice.summary().text);
1782 new_fragments.push_tree(slice, &None);
1783 fragment_start = old_fragments.start().offset();
1784 }
1785
1786 // If we are at the end of a non-concurrent fragment, advance to the next one.
1787 let fragment_end = old_fragments.end(&cx).offset();
1788 if fragment_end == range.start && fragment_end > fragment_start {
1789 let mut fragment = old_fragments.item().unwrap().clone();
1790 fragment.len = fragment_end - fragment_start;
1791 new_ropes.push_fragment(&fragment, fragment.visible);
1792 new_fragments.push(fragment, &None);
1793 old_fragments.next(&cx);
1794 fragment_start = old_fragments.start().offset();
1795 }
1796
1797 // Skip over insertions that are concurrent to this edit, but have a lower lamport
1798 // timestamp.
1799 while let Some(fragment) = old_fragments.item() {
1800 if fragment_start == range.start
1801 && fragment.timestamp.lamport() > timestamp.lamport()
1802 {
1803 new_ropes.push_fragment(fragment, fragment.visible);
1804 new_fragments.push(fragment.clone(), &None);
1805 old_fragments.next(&cx);
1806 debug_assert_eq!(fragment_start, range.start);
1807 } else {
1808 break;
1809 }
1810 }
1811 debug_assert!(fragment_start <= range.start);
1812
1813 // Preserve any portion of the current fragment that precedes this range.
1814 if fragment_start < range.start {
1815 let mut prefix = old_fragments.item().unwrap().clone();
1816 prefix.len = range.start - fragment_start;
1817 fragment_start = range.start;
1818 new_ropes.push_fragment(&prefix, prefix.visible);
1819 new_fragments.push(prefix, &None);
1820 }
1821
1822 // Insert the new text before any existing fragments within the range.
1823 if let Some(new_text) = new_text {
1824 new_ropes.push_str(new_text);
1825 new_fragments.push(
1826 Fragment {
1827 timestamp,
1828 len: new_text.len(),
1829 deletions: Default::default(),
1830 max_undos: Default::default(),
1831 visible: true,
1832 },
1833 &None,
1834 );
1835 }
1836
1837 // Advance through every fragment that intersects this range, marking the intersecting
1838 // portions as deleted.
1839 while fragment_start < range.end {
1840 let fragment = old_fragments.item().unwrap();
1841 let fragment_end = old_fragments.end(&cx).offset();
1842 let mut intersection = fragment.clone();
1843 let intersection_end = cmp::min(range.end, fragment_end);
1844 if fragment.was_visible(version, &self.undo_map) {
1845 intersection.len = intersection_end - fragment_start;
1846 intersection.deletions.insert(timestamp.local());
1847 intersection.visible = false;
1848 }
1849 if intersection.len > 0 {
1850 new_ropes.push_fragment(&intersection, fragment.visible);
1851 new_fragments.push(intersection, &None);
1852 fragment_start = intersection_end;
1853 }
1854 if fragment_end <= range.end {
1855 old_fragments.next(&cx);
1856 }
1857 }
1858 }
1859
1860 // If the current fragment has been partially consumed, then consume the rest of it
1861 // and advance to the next fragment before slicing.
1862 if fragment_start > old_fragments.start().offset() {
1863 let fragment_end = old_fragments.end(&cx).offset();
1864 if fragment_end > fragment_start {
1865 let mut suffix = old_fragments.item().unwrap().clone();
1866 suffix.len = fragment_end - fragment_start;
1867 new_ropes.push_fragment(&suffix, suffix.visible);
1868 new_fragments.push(suffix, &None);
1869 }
1870 old_fragments.next(&cx);
1871 }
1872
1873 let suffix = old_fragments.suffix(&cx);
1874 new_ropes.push_tree(suffix.summary().text);
1875 new_fragments.push_tree(suffix, &None);
1876 let (visible_text, deleted_text) = new_ropes.finish();
1877 drop(old_fragments);
1878
1879 self.fragments = new_fragments;
1880 self.visible_text = visible_text;
1881 self.deleted_text = deleted_text;
1882 self.local_clock.observe(timestamp.local());
1883 self.lamport_clock.observe(timestamp.lamport());
1884 }
1885
1886 #[cfg(not(test))]
1887 pub fn send_operation(&mut self, operation: Operation, cx: &mut ModelContext<Self>) {
1888 if let Some(file) = &self.file {
1889 file.buffer_updated(self.remote_id, operation, cx.as_mut());
1890 }
1891 }
1892
1893 #[cfg(test)]
1894 pub fn send_operation(&mut self, operation: Operation, _: &mut ModelContext<Self>) {
1895 self.operations.push(operation);
1896 }
1897
1898 pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut ModelContext<Self>) {
1899 self.selections
1900 .retain(|set_id, _| set_id.replica_id != replica_id);
1901 cx.notify();
1902 }
1903
1904 pub fn undo(&mut self, cx: &mut ModelContext<Self>) {
1905 let was_dirty = self.is_dirty();
1906 let old_version = self.version.clone();
1907
1908 if let Some(transaction) = self.history.pop_undo().cloned() {
1909 let selections = transaction.selections_before.clone();
1910 self.undo_or_redo(transaction, cx).unwrap();
1911 if let Some((set_id, selections)) = selections {
1912 let _ = self.update_selection_set(set_id, selections, cx);
1913 }
1914 }
1915
1916 cx.notify();
1917 if self.edits_since(old_version).next().is_some() {
1918 self.did_edit(was_dirty, cx);
1919 self.reparse(cx);
1920 }
1921 }
1922
1923 pub fn redo(&mut self, cx: &mut ModelContext<Self>) {
1924 let was_dirty = self.is_dirty();
1925 let old_version = self.version.clone();
1926
1927 if let Some(transaction) = self.history.pop_redo().cloned() {
1928 let selections = transaction.selections_after.clone();
1929 self.undo_or_redo(transaction, cx).unwrap();
1930 if let Some((set_id, selections)) = selections {
1931 let _ = self.update_selection_set(set_id, selections, cx);
1932 }
1933 }
1934
1935 cx.notify();
1936 if self.edits_since(old_version).next().is_some() {
1937 self.did_edit(was_dirty, cx);
1938 self.reparse(cx);
1939 }
1940 }
1941
1942 fn undo_or_redo(
1943 &mut self,
1944 transaction: Transaction,
1945 cx: &mut ModelContext<Self>,
1946 ) -> Result<()> {
1947 let mut counts = HashMap::default();
1948 for edit_id in transaction.edits {
1949 counts.insert(edit_id, self.undo_map.undo_count(edit_id) + 1);
1950 }
1951
1952 let undo = UndoOperation {
1953 id: self.local_clock.tick(),
1954 counts,
1955 ranges: transaction.ranges,
1956 version: transaction.start.clone(),
1957 };
1958 self.apply_undo(&undo)?;
1959 self.version.observe(undo.id);
1960
1961 let operation = Operation::Undo {
1962 undo,
1963 lamport_timestamp: self.lamport_clock.tick(),
1964 };
1965 self.send_operation(operation, cx);
1966
1967 Ok(())
1968 }
1969
1970 fn apply_undo(&mut self, undo: &UndoOperation) -> Result<()> {
1971 self.undo_map.insert(undo);
1972
1973 let mut cx = undo.version.clone();
1974 for edit_id in undo.counts.keys().copied() {
1975 cx.observe(edit_id);
1976 }
1977 let cx = Some(cx);
1978
1979 let mut old_fragments = self.fragments.cursor::<VersionedOffset>();
1980 let mut new_fragments = old_fragments.slice(
1981 &VersionedOffset::Offset(undo.ranges[0].start),
1982 Bias::Right,
1983 &cx,
1984 );
1985 let mut new_ropes =
1986 RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
1987 new_ropes.push_tree(new_fragments.summary().text);
1988
1989 for range in &undo.ranges {
1990 let mut end_offset = old_fragments.end(&cx).offset();
1991
1992 if end_offset < range.start {
1993 let preceding_fragments =
1994 old_fragments.slice(&VersionedOffset::Offset(range.start), Bias::Right, &cx);
1995 new_ropes.push_tree(preceding_fragments.summary().text);
1996 new_fragments.push_tree(preceding_fragments, &None);
1997 }
1998
1999 while end_offset <= range.end {
2000 if let Some(fragment) = old_fragments.item() {
2001 let mut fragment = fragment.clone();
2002 let fragment_was_visible = fragment.visible;
2003
2004 if fragment.was_visible(&undo.version, &self.undo_map)
2005 || undo.counts.contains_key(&fragment.timestamp.local())
2006 {
2007 fragment.visible = fragment.is_visible(&self.undo_map);
2008 fragment.max_undos.observe(undo.id);
2009 }
2010 new_ropes.push_fragment(&fragment, fragment_was_visible);
2011 new_fragments.push(fragment, &None);
2012
2013 old_fragments.next(&cx);
2014 if end_offset == old_fragments.end(&cx).offset() {
2015 let unseen_fragments = old_fragments.slice(
2016 &VersionedOffset::Offset(end_offset),
2017 Bias::Right,
2018 &cx,
2019 );
2020 new_ropes.push_tree(unseen_fragments.summary().text);
2021 new_fragments.push_tree(unseen_fragments, &None);
2022 }
2023 end_offset = old_fragments.end(&cx).offset();
2024 } else {
2025 break;
2026 }
2027 }
2028 }
2029
2030 let suffix = old_fragments.suffix(&cx);
2031 new_ropes.push_tree(suffix.summary().text);
2032 new_fragments.push_tree(suffix, &None);
2033
2034 drop(old_fragments);
2035 let (visible_text, deleted_text) = new_ropes.finish();
2036 self.fragments = new_fragments;
2037 self.visible_text = visible_text;
2038 self.deleted_text = deleted_text;
2039 Ok(())
2040 }
2041
2042 fn flush_deferred_ops(&mut self) -> Result<()> {
2043 self.deferred_replicas.clear();
2044 let mut deferred_ops = Vec::new();
2045 for op in self.deferred_ops.drain().cursor().cloned() {
2046 if self.can_apply_op(&op) {
2047 self.apply_op(op)?;
2048 } else {
2049 self.deferred_replicas.insert(op.replica_id());
2050 deferred_ops.push(op);
2051 }
2052 }
2053 self.deferred_ops.insert(deferred_ops);
2054 Ok(())
2055 }
2056
2057 fn can_apply_op(&self, op: &Operation) -> bool {
2058 if self.deferred_replicas.contains(&op.replica_id()) {
2059 false
2060 } else {
2061 match op {
2062 Operation::Edit(edit) => self.version >= edit.version,
2063 Operation::Undo { undo, .. } => self.version >= undo.version,
2064 Operation::UpdateSelections { selections, .. } => {
2065 if let Some(selections) = selections {
2066 selections.iter().all(|selection| {
2067 let contains_start = self.version >= selection.start.version;
2068 let contains_end = self.version >= selection.end.version;
2069 contains_start && contains_end
2070 })
2071 } else {
2072 true
2073 }
2074 }
2075 Operation::SetActiveSelections { set_id, .. } => {
2076 set_id.map_or(true, |set_id| self.selections.contains_key(&set_id))
2077 }
2078 #[cfg(test)]
2079 Operation::Test(_) => true,
2080 }
2081 }
2082 }
2083
2084 fn apply_local_edit(
2085 &mut self,
2086 ranges: &[Range<usize>],
2087 new_text: Option<String>,
2088 timestamp: InsertionTimestamp,
2089 ) -> EditOperation {
2090 let mut edit = EditOperation {
2091 timestamp,
2092 version: self.version(),
2093 ranges: Vec::with_capacity(ranges.len()),
2094 new_text: None,
2095 };
2096
2097 let mut new_ropes =
2098 RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
2099 let mut old_fragments = self.fragments.cursor::<FragmentTextSummary>();
2100 let mut new_fragments = old_fragments.slice(&ranges[0].start, Bias::Right, &None);
2101 new_ropes.push_tree(new_fragments.summary().text);
2102
2103 let mut fragment_start = old_fragments.start().visible;
2104 for range in ranges {
2105 let fragment_end = old_fragments.end(&None).visible;
2106
2107 // If the current fragment ends before this range, then jump ahead to the first fragment
2108 // that extends past the start of this range, reusing any intervening fragments.
2109 if fragment_end < range.start {
2110 // If the current fragment has been partially consumed, then consume the rest of it
2111 // and advance to the next fragment before slicing.
2112 if fragment_start > old_fragments.start().visible {
2113 if fragment_end > fragment_start {
2114 let mut suffix = old_fragments.item().unwrap().clone();
2115 suffix.len = fragment_end - fragment_start;
2116 new_ropes.push_fragment(&suffix, suffix.visible);
2117 new_fragments.push(suffix, &None);
2118 }
2119 old_fragments.next(&None);
2120 }
2121
2122 let slice = old_fragments.slice(&range.start, Bias::Right, &None);
2123 new_ropes.push_tree(slice.summary().text);
2124 new_fragments.push_tree(slice, &None);
2125 fragment_start = old_fragments.start().visible;
2126 }
2127
2128 let full_range_start = range.start + old_fragments.start().deleted;
2129
2130 // Preserve any portion of the current fragment that precedes this range.
2131 if fragment_start < range.start {
2132 let mut prefix = old_fragments.item().unwrap().clone();
2133 prefix.len = range.start - fragment_start;
2134 new_ropes.push_fragment(&prefix, prefix.visible);
2135 new_fragments.push(prefix, &None);
2136 fragment_start = range.start;
2137 }
2138
2139 // Insert the new text before any existing fragments within the range.
2140 if let Some(new_text) = new_text.as_deref() {
2141 new_ropes.push_str(new_text);
2142 new_fragments.push(
2143 Fragment {
2144 timestamp,
2145 len: new_text.len(),
2146 deletions: Default::default(),
2147 max_undos: Default::default(),
2148 visible: true,
2149 },
2150 &None,
2151 );
2152 }
2153
2154 // Advance through every fragment that intersects this range, marking the intersecting
2155 // portions as deleted.
2156 while fragment_start < range.end {
2157 let fragment = old_fragments.item().unwrap();
2158 let fragment_end = old_fragments.end(&None).visible;
2159 let mut intersection = fragment.clone();
2160 let intersection_end = cmp::min(range.end, fragment_end);
2161 if fragment.visible {
2162 intersection.len = intersection_end - fragment_start;
2163 intersection.deletions.insert(timestamp.local());
2164 intersection.visible = false;
2165 }
2166 if intersection.len > 0 {
2167 new_ropes.push_fragment(&intersection, fragment.visible);
2168 new_fragments.push(intersection, &None);
2169 fragment_start = intersection_end;
2170 }
2171 if fragment_end <= range.end {
2172 old_fragments.next(&None);
2173 }
2174 }
2175
2176 let full_range_end = range.end + old_fragments.start().deleted;
2177 edit.ranges.push(full_range_start..full_range_end);
2178 }
2179
2180 // If the current fragment has been partially consumed, then consume the rest of it
2181 // and advance to the next fragment before slicing.
2182 if fragment_start > old_fragments.start().visible {
2183 let fragment_end = old_fragments.end(&None).visible;
2184 if fragment_end > fragment_start {
2185 let mut suffix = old_fragments.item().unwrap().clone();
2186 suffix.len = fragment_end - fragment_start;
2187 new_ropes.push_fragment(&suffix, suffix.visible);
2188 new_fragments.push(suffix, &None);
2189 }
2190 old_fragments.next(&None);
2191 }
2192
2193 let suffix = old_fragments.suffix(&None);
2194 new_ropes.push_tree(suffix.summary().text);
2195 new_fragments.push_tree(suffix, &None);
2196 let (visible_text, deleted_text) = new_ropes.finish();
2197 drop(old_fragments);
2198
2199 self.fragments = new_fragments;
2200 self.visible_text = visible_text;
2201 self.deleted_text = deleted_text;
2202 edit.new_text = new_text;
2203 edit
2204 }
2205
2206 fn content<'a>(&'a self) -> Content<'a> {
2207 self.into()
2208 }
2209
2210 pub fn text_summary_for_range(&self, range: Range<usize>) -> TextSummary {
2211 self.content().text_summary_for_range(range)
2212 }
2213
2214 pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
2215 self.anchor_at(position, Bias::Left)
2216 }
2217
2218 pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
2219 self.anchor_at(position, Bias::Right)
2220 }
2221
2222 pub fn anchor_at<T: ToOffset>(&self, position: T, bias: Bias) -> Anchor {
2223 self.content().anchor_at(position, bias)
2224 }
2225
2226 pub fn point_for_offset(&self, offset: usize) -> Result<Point> {
2227 self.content().point_for_offset(offset)
2228 }
2229
2230 pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
2231 self.visible_text.clip_point(point, bias)
2232 }
2233
2234 pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
2235 self.visible_text.clip_offset(offset, bias)
2236 }
2237}
2238
2239#[cfg(any(test, feature = "test-support"))]
2240impl Buffer {
2241 fn random_byte_range(&mut self, start_offset: usize, rng: &mut impl rand::Rng) -> Range<usize> {
2242 let end = self.clip_offset(rng.gen_range(start_offset..=self.len()), Bias::Right);
2243 let start = self.clip_offset(rng.gen_range(start_offset..=end), Bias::Right);
2244 start..end
2245 }
2246
2247 pub fn randomly_edit<T>(
2248 &mut self,
2249 rng: &mut T,
2250 old_range_count: usize,
2251 cx: &mut ModelContext<Self>,
2252 ) -> (Vec<Range<usize>>, String)
2253 where
2254 T: rand::Rng,
2255 {
2256 let mut old_ranges: Vec<Range<usize>> = Vec::new();
2257 for _ in 0..old_range_count {
2258 let last_end = old_ranges.last().map_or(0, |last_range| last_range.end + 1);
2259 if last_end > self.len() {
2260 break;
2261 }
2262 old_ranges.push(self.random_byte_range(last_end, rng));
2263 }
2264 let new_text_len = rng.gen_range(0..10);
2265 let new_text: String = crate::random_char_iter::RandomCharIter::new(&mut *rng)
2266 .take(new_text_len)
2267 .collect();
2268 log::info!(
2269 "mutating buffer {} at {:?}: {:?}",
2270 self.replica_id,
2271 old_ranges,
2272 new_text
2273 );
2274 self.edit(old_ranges.iter().cloned(), new_text.as_str(), cx);
2275 (old_ranges, new_text)
2276 }
2277
2278 pub fn randomly_mutate<T>(
2279 &mut self,
2280 rng: &mut T,
2281 cx: &mut ModelContext<Self>,
2282 ) -> (Vec<Range<usize>>, String)
2283 where
2284 T: rand::Rng,
2285 {
2286 use rand::prelude::*;
2287
2288 let (old_ranges, new_text) = self.randomly_edit(rng, 5, cx);
2289
2290 // Randomly add, remove or mutate selection sets.
2291 let replica_selection_sets = &self
2292 .selection_sets()
2293 .map(|(set_id, _)| *set_id)
2294 .filter(|set_id| self.replica_id == set_id.replica_id)
2295 .collect::<Vec<_>>();
2296 let set_id = replica_selection_sets.choose(rng);
2297 if set_id.is_some() && rng.gen_bool(1.0 / 6.0) {
2298 self.remove_selection_set(*set_id.unwrap(), cx).unwrap();
2299 } else {
2300 let mut ranges = Vec::new();
2301 for _ in 0..5 {
2302 ranges.push(self.random_byte_range(0, rng));
2303 }
2304 let new_selections = self.selections_from_ranges(ranges).unwrap();
2305
2306 if set_id.is_none() || rng.gen_bool(1.0 / 5.0) {
2307 self.add_selection_set(new_selections, cx);
2308 } else {
2309 self.update_selection_set(*set_id.unwrap(), new_selections, cx)
2310 .unwrap();
2311 }
2312 }
2313
2314 (old_ranges, new_text)
2315 }
2316
2317 pub fn randomly_undo_redo(&mut self, rng: &mut impl rand::Rng, cx: &mut ModelContext<Self>) {
2318 use rand::prelude::*;
2319
2320 for _ in 0..rng.gen_range(1..=5) {
2321 if let Some(transaction) = self.history.undo_stack.choose(rng).cloned() {
2322 log::info!(
2323 "undoing buffer {} transaction {:?}",
2324 self.replica_id,
2325 transaction
2326 );
2327 self.undo_or_redo(transaction, cx).unwrap();
2328 }
2329 }
2330 }
2331
2332 fn selections_from_ranges<I>(&self, ranges: I) -> Result<Vec<Selection>>
2333 where
2334 I: IntoIterator<Item = Range<usize>>,
2335 {
2336 use std::sync::atomic::{self, AtomicUsize};
2337
2338 static NEXT_SELECTION_ID: AtomicUsize = AtomicUsize::new(0);
2339
2340 let mut ranges = ranges.into_iter().collect::<Vec<_>>();
2341 ranges.sort_unstable_by_key(|range| range.start);
2342
2343 let mut selections = Vec::with_capacity(ranges.len());
2344 for range in ranges {
2345 if range.start > range.end {
2346 selections.push(Selection {
2347 id: NEXT_SELECTION_ID.fetch_add(1, atomic::Ordering::SeqCst),
2348 start: self.anchor_before(range.end),
2349 end: self.anchor_before(range.start),
2350 reversed: true,
2351 goal: SelectionGoal::None,
2352 });
2353 } else {
2354 selections.push(Selection {
2355 id: NEXT_SELECTION_ID.fetch_add(1, atomic::Ordering::SeqCst),
2356 start: self.anchor_after(range.start),
2357 end: self.anchor_before(range.end),
2358 reversed: false,
2359 goal: SelectionGoal::None,
2360 });
2361 }
2362 }
2363 Ok(selections)
2364 }
2365
2366 pub fn selection_ranges<'a>(&'a self, set_id: SelectionSetId) -> Result<Vec<Range<usize>>> {
2367 Ok(self
2368 .selection_set(set_id)?
2369 .selections
2370 .iter()
2371 .map(move |selection| {
2372 let start = selection.start.to_offset(self);
2373 let end = selection.end.to_offset(self);
2374 if selection.reversed {
2375 end..start
2376 } else {
2377 start..end
2378 }
2379 })
2380 .collect())
2381 }
2382
2383 pub fn all_selection_ranges<'a>(
2384 &'a self,
2385 ) -> impl 'a + Iterator<Item = (SelectionSetId, Vec<Range<usize>>)> {
2386 self.selections
2387 .keys()
2388 .map(move |set_id| (*set_id, self.selection_ranges(*set_id).unwrap()))
2389 }
2390
2391 pub fn enclosing_bracket_point_ranges<T: ToOffset>(
2392 &self,
2393 range: Range<T>,
2394 ) -> Option<(Range<Point>, Range<Point>)> {
2395 self.enclosing_bracket_ranges(range).map(|(start, end)| {
2396 let point_start = start.start.to_point(self)..start.end.to_point(self);
2397 let point_end = end.start.to_point(self)..end.end.to_point(self);
2398 (point_start, point_end)
2399 })
2400 }
2401}
2402
2403impl Clone for Buffer {
2404 fn clone(&self) -> Self {
2405 Self {
2406 fragments: self.fragments.clone(),
2407 visible_text: self.visible_text.clone(),
2408 deleted_text: self.deleted_text.clone(),
2409 version: self.version.clone(),
2410 saved_version: self.saved_version.clone(),
2411 saved_mtime: self.saved_mtime,
2412 last_edit: self.last_edit.clone(),
2413 undo_map: self.undo_map.clone(),
2414 history: self.history.clone(),
2415 selections: self.selections.clone(),
2416 deferred_ops: self.deferred_ops.clone(),
2417 file: self.file.as_ref().map(|f| f.boxed_clone()),
2418 language: self.language.clone(),
2419 syntax_tree: Mutex::new(self.syntax_tree.lock().clone()),
2420 parsing_in_background: false,
2421 sync_parse_timeout: self.sync_parse_timeout,
2422 parse_count: self.parse_count,
2423 autoindent_requests: Default::default(),
2424 pending_autoindent: Default::default(),
2425 deferred_replicas: self.deferred_replicas.clone(),
2426 replica_id: self.replica_id,
2427 remote_id: self.remote_id.clone(),
2428 local_clock: self.local_clock.clone(),
2429 lamport_clock: self.lamport_clock.clone(),
2430
2431 #[cfg(test)]
2432 operations: self.operations.clone(),
2433 }
2434 }
2435}
2436
2437pub struct Snapshot {
2438 visible_text: Rope,
2439 fragments: SumTree<Fragment>,
2440 version: clock::Global,
2441 tree: Option<Tree>,
2442 is_parsing: bool,
2443 language: Option<Arc<Language>>,
2444 query_cursor: QueryCursorHandle,
2445}
2446
2447impl Clone for Snapshot {
2448 fn clone(&self) -> Self {
2449 Self {
2450 visible_text: self.visible_text.clone(),
2451 fragments: self.fragments.clone(),
2452 version: self.version.clone(),
2453 tree: self.tree.clone(),
2454 is_parsing: self.is_parsing,
2455 language: self.language.clone(),
2456 query_cursor: QueryCursorHandle::new(),
2457 }
2458 }
2459}
2460
2461impl Snapshot {
2462 pub fn len(&self) -> usize {
2463 self.visible_text.len()
2464 }
2465
2466 pub fn line_len(&self, row: u32) -> u32 {
2467 self.content().line_len(row)
2468 }
2469
2470 pub fn indent_column_for_line(&self, row: u32) -> u32 {
2471 self.content().indent_column_for_line(row)
2472 }
2473
2474 fn suggest_autoindents<'a>(
2475 &'a self,
2476 row_range: Range<u32>,
2477 ) -> Option<impl Iterator<Item = IndentSuggestion> + 'a> {
2478 let mut query_cursor = QueryCursorHandle::new();
2479 if let Some((language, tree)) = self.language.as_ref().zip(self.tree.as_ref()) {
2480 let prev_non_blank_row = self.prev_non_blank_row(row_range.start);
2481
2482 // Get the "indentation ranges" that intersect this row range.
2483 let indent_capture_ix = language.indents_query.capture_index_for_name("indent");
2484 let end_capture_ix = language.indents_query.capture_index_for_name("end");
2485 query_cursor.set_point_range(
2486 Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0).into()
2487 ..Point::new(row_range.end, 0).into(),
2488 );
2489 let mut indentation_ranges = Vec::<(Range<Point>, &'static str)>::new();
2490 for mat in query_cursor.matches(
2491 &language.indents_query,
2492 tree.root_node(),
2493 TextProvider(&self.visible_text),
2494 ) {
2495 let mut node_kind = "";
2496 let mut start: Option<Point> = None;
2497 let mut end: Option<Point> = None;
2498 for capture in mat.captures {
2499 if Some(capture.index) == indent_capture_ix {
2500 node_kind = capture.node.kind();
2501 start.get_or_insert(capture.node.start_position().into());
2502 end.get_or_insert(capture.node.end_position().into());
2503 } else if Some(capture.index) == end_capture_ix {
2504 end = Some(capture.node.start_position().into());
2505 }
2506 }
2507
2508 if let Some((start, end)) = start.zip(end) {
2509 if start.row == end.row {
2510 continue;
2511 }
2512
2513 let range = start..end;
2514 match indentation_ranges.binary_search_by_key(&range.start, |r| r.0.start) {
2515 Err(ix) => indentation_ranges.insert(ix, (range, node_kind)),
2516 Ok(ix) => {
2517 let prev_range = &mut indentation_ranges[ix];
2518 prev_range.0.end = prev_range.0.end.max(range.end);
2519 }
2520 }
2521 }
2522 }
2523
2524 let mut prev_row = prev_non_blank_row.unwrap_or(0);
2525 Some(row_range.map(move |row| {
2526 let row_start = Point::new(row, self.indent_column_for_line(row));
2527
2528 let mut indent_from_prev_row = false;
2529 let mut outdent_to_row = u32::MAX;
2530 for (range, _node_kind) in &indentation_ranges {
2531 if range.start.row >= row {
2532 break;
2533 }
2534
2535 if range.start.row == prev_row && range.end > row_start {
2536 indent_from_prev_row = true;
2537 }
2538 if range.end.row >= prev_row && range.end <= row_start {
2539 outdent_to_row = outdent_to_row.min(range.start.row);
2540 }
2541 }
2542
2543 let suggestion = if outdent_to_row == prev_row {
2544 IndentSuggestion {
2545 basis_row: prev_row,
2546 indent: false,
2547 }
2548 } else if indent_from_prev_row {
2549 IndentSuggestion {
2550 basis_row: prev_row,
2551 indent: true,
2552 }
2553 } else if outdent_to_row < prev_row {
2554 IndentSuggestion {
2555 basis_row: outdent_to_row,
2556 indent: false,
2557 }
2558 } else {
2559 IndentSuggestion {
2560 basis_row: prev_row,
2561 indent: false,
2562 }
2563 };
2564
2565 prev_row = row;
2566 suggestion
2567 }))
2568 } else {
2569 None
2570 }
2571 }
2572
2573 fn prev_non_blank_row(&self, mut row: u32) -> Option<u32> {
2574 while row > 0 {
2575 row -= 1;
2576 if !self.is_line_blank(row) {
2577 return Some(row);
2578 }
2579 }
2580 None
2581 }
2582
2583 fn is_line_blank(&self, row: u32) -> bool {
2584 self.text_for_range(Point::new(row, 0)..Point::new(row, self.line_len(row)))
2585 .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
2586 }
2587
2588 pub fn text(&self) -> Rope {
2589 self.visible_text.clone()
2590 }
2591
2592 pub fn text_summary(&self) -> TextSummary {
2593 self.visible_text.summary()
2594 }
2595
2596 pub fn max_point(&self) -> Point {
2597 self.visible_text.max_point()
2598 }
2599
2600 pub fn text_for_range<T: ToOffset>(&self, range: Range<T>) -> Chunks {
2601 let range = range.start.to_offset(self)..range.end.to_offset(self);
2602 self.visible_text.chunks_in_range(range)
2603 }
2604
2605 pub fn highlighted_text_for_range<T: ToOffset>(
2606 &mut self,
2607 range: Range<T>,
2608 ) -> HighlightedChunks {
2609 let range = range.start.to_offset(&*self)..range.end.to_offset(&*self);
2610 let chunks = self.visible_text.chunks_in_range(range.clone());
2611 if let Some((language, tree)) = self.language.as_ref().zip(self.tree.as_ref()) {
2612 let captures = self.query_cursor.set_byte_range(range.clone()).captures(
2613 &language.highlights_query,
2614 tree.root_node(),
2615 TextProvider(&self.visible_text),
2616 );
2617
2618 HighlightedChunks {
2619 range,
2620 chunks,
2621 highlights: Some(Highlights {
2622 captures,
2623 next_capture: None,
2624 stack: Default::default(),
2625 highlight_map: language.highlight_map(),
2626 }),
2627 }
2628 } else {
2629 HighlightedChunks {
2630 range,
2631 chunks,
2632 highlights: None,
2633 }
2634 }
2635 }
2636
2637 pub fn text_summary_for_range<T>(&self, range: Range<T>) -> TextSummary
2638 where
2639 T: ToOffset,
2640 {
2641 let range = range.start.to_offset(self.content())..range.end.to_offset(self.content());
2642 self.content().text_summary_for_range(range)
2643 }
2644
2645 pub fn point_for_offset(&self, offset: usize) -> Result<Point> {
2646 self.content().point_for_offset(offset)
2647 }
2648
2649 pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
2650 self.visible_text.clip_offset(offset, bias)
2651 }
2652
2653 pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
2654 self.visible_text.clip_point(point, bias)
2655 }
2656
2657 pub fn to_offset(&self, point: Point) -> usize {
2658 self.visible_text.to_offset(point)
2659 }
2660
2661 pub fn to_point(&self, offset: usize) -> Point {
2662 self.visible_text.to_point(offset)
2663 }
2664
2665 pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
2666 self.content().anchor_at(position, Bias::Left)
2667 }
2668
2669 pub fn anchor_after<T: ToOffset>(&self, position: T) -> Anchor {
2670 self.content().anchor_at(position, Bias::Right)
2671 }
2672
2673 fn content(&self) -> Content {
2674 self.into()
2675 }
2676}
2677
2678pub struct Content<'a> {
2679 visible_text: &'a Rope,
2680 fragments: &'a SumTree<Fragment>,
2681 version: &'a clock::Global,
2682}
2683
2684impl<'a> From<&'a Snapshot> for Content<'a> {
2685 fn from(snapshot: &'a Snapshot) -> Self {
2686 Self {
2687 visible_text: &snapshot.visible_text,
2688 fragments: &snapshot.fragments,
2689 version: &snapshot.version,
2690 }
2691 }
2692}
2693
2694impl<'a> From<&'a Buffer> for Content<'a> {
2695 fn from(buffer: &'a Buffer) -> Self {
2696 Self {
2697 visible_text: &buffer.visible_text,
2698 fragments: &buffer.fragments,
2699 version: &buffer.version,
2700 }
2701 }
2702}
2703
2704impl<'a> From<&'a mut Buffer> for Content<'a> {
2705 fn from(buffer: &'a mut Buffer) -> Self {
2706 Self {
2707 visible_text: &buffer.visible_text,
2708 fragments: &buffer.fragments,
2709 version: &buffer.version,
2710 }
2711 }
2712}
2713
2714impl<'a> From<&'a Content<'a>> for Content<'a> {
2715 fn from(content: &'a Content) -> Self {
2716 Self {
2717 visible_text: &content.visible_text,
2718 fragments: &content.fragments,
2719 version: &content.version,
2720 }
2721 }
2722}
2723
2724impl<'a> Content<'a> {
2725 fn max_point(&self) -> Point {
2726 self.visible_text.max_point()
2727 }
2728
2729 fn len(&self) -> usize {
2730 self.fragments.extent::<usize>(&None)
2731 }
2732
2733 pub fn chars_at<T: ToOffset>(&self, position: T) -> impl Iterator<Item = char> + 'a {
2734 let offset = position.to_offset(self);
2735 self.visible_text.chars_at(offset)
2736 }
2737
2738 pub fn text_for_range<T: ToOffset>(&self, range: Range<T>) -> Chunks<'a> {
2739 let start = range.start.to_offset(self);
2740 let end = range.end.to_offset(self);
2741 self.visible_text.chunks_in_range(start..end)
2742 }
2743
2744 fn line_len(&self, row: u32) -> u32 {
2745 let row_start_offset = Point::new(row, 0).to_offset(self);
2746 let row_end_offset = if row >= self.max_point().row {
2747 self.len()
2748 } else {
2749 Point::new(row + 1, 0).to_offset(self) - 1
2750 };
2751 (row_end_offset - row_start_offset) as u32
2752 }
2753
2754 pub fn indent_column_for_line(&self, row: u32) -> u32 {
2755 let mut result = 0;
2756 for c in self.chars_at(Point::new(row, 0)) {
2757 if c == ' ' {
2758 result += 1;
2759 } else {
2760 break;
2761 }
2762 }
2763 result
2764 }
2765
2766 fn summary_for_anchor(&self, anchor: &Anchor) -> TextSummary {
2767 let cx = Some(anchor.version.clone());
2768 let mut cursor = self.fragments.cursor::<(VersionedOffset, usize)>();
2769 cursor.seek(&VersionedOffset::Offset(anchor.offset), anchor.bias, &cx);
2770 let overshoot = if cursor.item().map_or(false, |fragment| fragment.visible) {
2771 anchor.offset - cursor.start().0.offset()
2772 } else {
2773 0
2774 };
2775 self.text_summary_for_range(0..cursor.start().1 + overshoot)
2776 }
2777
2778 fn text_summary_for_range(&self, range: Range<usize>) -> TextSummary {
2779 self.visible_text.cursor(range.start).summary(range.end)
2780 }
2781
2782 fn summaries_for_anchors<T>(
2783 &self,
2784 map: &'a AnchorMap<T>,
2785 ) -> impl Iterator<Item = (TextSummary, &'a T)> {
2786 let cx = Some(map.version.clone());
2787 let mut summary = TextSummary::default();
2788 let mut rope_cursor = self.visible_text.cursor(0);
2789 let mut cursor = self.fragments.cursor::<(VersionedOffset, usize)>();
2790 map.entries.iter().map(move |((offset, bias), value)| {
2791 cursor.seek_forward(&VersionedOffset::Offset(*offset), *bias, &cx);
2792 let overshoot = if cursor.item().map_or(false, |fragment| fragment.visible) {
2793 offset - cursor.start().0.offset()
2794 } else {
2795 0
2796 };
2797 summary += rope_cursor.summary(cursor.start().1 + overshoot);
2798 (summary.clone(), value)
2799 })
2800 }
2801
2802 fn summaries_for_anchor_ranges<T>(
2803 &self,
2804 map: &'a AnchorRangeMap<T>,
2805 ) -> impl Iterator<Item = (Range<TextSummary>, &'a T)> {
2806 let cx = Some(map.version.clone());
2807 let mut summary = TextSummary::default();
2808 let mut rope_cursor = self.visible_text.cursor(0);
2809 let mut cursor = self.fragments.cursor::<(VersionedOffset, usize)>();
2810 map.entries.iter().map(move |(range, value)| {
2811 let Range {
2812 start: (start_offset, start_bias),
2813 end: (end_offset, end_bias),
2814 } = range;
2815
2816 cursor.seek_forward(&VersionedOffset::Offset(*start_offset), *start_bias, &cx);
2817 let overshoot = if cursor.item().map_or(false, |fragment| fragment.visible) {
2818 start_offset - cursor.start().0.offset()
2819 } else {
2820 0
2821 };
2822 summary += rope_cursor.summary(cursor.start().1 + overshoot);
2823 let start_summary = summary.clone();
2824
2825 cursor.seek_forward(&VersionedOffset::Offset(*end_offset), *end_bias, &cx);
2826 let overshoot = if cursor.item().map_or(false, |fragment| fragment.visible) {
2827 end_offset - cursor.start().0.offset()
2828 } else {
2829 0
2830 };
2831 summary += rope_cursor.summary(cursor.start().1 + overshoot);
2832 let end_summary = summary.clone();
2833
2834 (start_summary..end_summary, value)
2835 })
2836 }
2837
2838 fn anchor_at<T: ToOffset>(&self, position: T, bias: Bias) -> Anchor {
2839 let offset = position.to_offset(self);
2840 let max_offset = self.len();
2841 assert!(offset <= max_offset, "offset is out of range");
2842 let mut cursor = self.fragments.cursor::<FragmentTextSummary>();
2843 cursor.seek(&offset, bias, &None);
2844 Anchor {
2845 offset: offset + cursor.start().deleted,
2846 bias,
2847 version: self.version.clone(),
2848 }
2849 }
2850
2851 pub fn anchor_map<T, E>(&self, entries: E) -> AnchorMap<T>
2852 where
2853 E: IntoIterator<Item = ((usize, Bias), T)>,
2854 {
2855 let version = self.version.clone();
2856 let mut cursor = self.fragments.cursor::<FragmentTextSummary>();
2857 let entries = entries
2858 .into_iter()
2859 .map(|((offset, bias), value)| {
2860 cursor.seek_forward(&offset, bias, &None);
2861 let full_offset = cursor.start().deleted + offset;
2862 ((full_offset, bias), value)
2863 })
2864 .collect();
2865
2866 AnchorMap { version, entries }
2867 }
2868
2869 pub fn anchor_range_map<T, E>(&self, entries: E) -> AnchorRangeMap<T>
2870 where
2871 E: IntoIterator<Item = (Range<(usize, Bias)>, T)>,
2872 {
2873 let version = self.version.clone();
2874 let mut cursor = self.fragments.cursor::<FragmentTextSummary>();
2875 let entries = entries
2876 .into_iter()
2877 .map(|(range, value)| {
2878 let Range {
2879 start: (start_offset, start_bias),
2880 end: (end_offset, end_bias),
2881 } = range;
2882 cursor.seek_forward(&start_offset, start_bias, &None);
2883 let full_start_offset = cursor.start().deleted + start_offset;
2884 cursor.seek_forward(&end_offset, end_bias, &None);
2885 let full_end_offset = cursor.start().deleted + end_offset;
2886 (
2887 (full_start_offset, start_bias)..(full_end_offset, end_bias),
2888 value,
2889 )
2890 })
2891 .collect();
2892
2893 AnchorRangeMap { version, entries }
2894 }
2895
2896 pub fn anchor_set<E>(&self, entries: E) -> AnchorSet
2897 where
2898 E: IntoIterator<Item = (usize, Bias)>,
2899 {
2900 AnchorSet(self.anchor_map(entries.into_iter().map(|range| (range, ()))))
2901 }
2902
2903 pub fn anchor_range_set<E>(&self, entries: E) -> AnchorRangeSet
2904 where
2905 E: IntoIterator<Item = Range<(usize, Bias)>>,
2906 {
2907 AnchorRangeSet(self.anchor_range_map(entries.into_iter().map(|range| (range, ()))))
2908 }
2909
2910 fn full_offset_for_anchor(&self, anchor: &Anchor) -> usize {
2911 let cx = Some(anchor.version.clone());
2912 let mut cursor = self
2913 .fragments
2914 .cursor::<(VersionedOffset, FragmentTextSummary)>();
2915 cursor.seek(&VersionedOffset::Offset(anchor.offset), anchor.bias, &cx);
2916 let overshoot = if cursor.item().is_some() {
2917 anchor.offset - cursor.start().0.offset()
2918 } else {
2919 0
2920 };
2921 let summary = cursor.start().1;
2922 summary.visible + summary.deleted + overshoot
2923 }
2924
2925 fn point_for_offset(&self, offset: usize) -> Result<Point> {
2926 if offset <= self.len() {
2927 Ok(self.text_summary_for_range(0..offset).lines)
2928 } else {
2929 Err(anyhow!("offset out of bounds"))
2930 }
2931 }
2932}
2933
2934#[derive(Debug)]
2935struct IndentSuggestion {
2936 basis_row: u32,
2937 indent: bool,
2938}
2939
2940struct RopeBuilder<'a> {
2941 old_visible_cursor: rope::Cursor<'a>,
2942 old_deleted_cursor: rope::Cursor<'a>,
2943 new_visible: Rope,
2944 new_deleted: Rope,
2945}
2946
2947impl<'a> RopeBuilder<'a> {
2948 fn new(old_visible_cursor: rope::Cursor<'a>, old_deleted_cursor: rope::Cursor<'a>) -> Self {
2949 Self {
2950 old_visible_cursor,
2951 old_deleted_cursor,
2952 new_visible: Rope::new(),
2953 new_deleted: Rope::new(),
2954 }
2955 }
2956
2957 fn push_tree(&mut self, len: FragmentTextSummary) {
2958 self.push(len.visible, true, true);
2959 self.push(len.deleted, false, false);
2960 }
2961
2962 fn push_fragment(&mut self, fragment: &Fragment, was_visible: bool) {
2963 debug_assert!(fragment.len > 0);
2964 self.push(fragment.len, was_visible, fragment.visible)
2965 }
2966
2967 fn push(&mut self, len: usize, was_visible: bool, is_visible: bool) {
2968 let text = if was_visible {
2969 self.old_visible_cursor
2970 .slice(self.old_visible_cursor.offset() + len)
2971 } else {
2972 self.old_deleted_cursor
2973 .slice(self.old_deleted_cursor.offset() + len)
2974 };
2975 if is_visible {
2976 self.new_visible.append(text);
2977 } else {
2978 self.new_deleted.append(text);
2979 }
2980 }
2981
2982 fn push_str(&mut self, text: &str) {
2983 self.new_visible.push(text);
2984 }
2985
2986 fn finish(mut self) -> (Rope, Rope) {
2987 self.new_visible.append(self.old_visible_cursor.suffix());
2988 self.new_deleted.append(self.old_deleted_cursor.suffix());
2989 (self.new_visible, self.new_deleted)
2990 }
2991}
2992
2993#[derive(Clone, Debug, Eq, PartialEq)]
2994pub enum Event {
2995 Edited,
2996 Dirtied,
2997 Saved,
2998 FileHandleChanged,
2999 Reloaded,
3000 Reparsed,
3001 Closed,
3002}
3003
3004impl Entity for Buffer {
3005 type Event = Event;
3006
3007 fn release(&mut self, cx: &mut gpui::MutableAppContext) {
3008 if let Some(file) = self.file.as_ref() {
3009 file.buffer_removed(self.remote_id, cx);
3010 }
3011 }
3012}
3013
3014impl<'a, F: Fn(&FragmentSummary) -> bool> Iterator for Edits<'a, F> {
3015 type Item = Edit;
3016
3017 fn next(&mut self) -> Option<Self::Item> {
3018 let mut change: Option<Edit> = None;
3019 let cursor = self.cursor.as_mut()?;
3020
3021 while let Some(fragment) = cursor.item() {
3022 let bytes = cursor.start().visible - self.new_offset;
3023 let lines = self.visible_text.to_point(cursor.start().visible) - self.new_point;
3024 self.old_offset += bytes;
3025 self.old_point += &lines;
3026 self.new_offset += bytes;
3027 self.new_point += &lines;
3028
3029 if !fragment.was_visible(&self.since, &self.undos) && fragment.visible {
3030 let fragment_lines =
3031 self.visible_text.to_point(self.new_offset + fragment.len) - self.new_point;
3032 if let Some(ref mut change) = change {
3033 if change.new_bytes.end == self.new_offset {
3034 change.new_bytes.end += fragment.len;
3035 } else {
3036 break;
3037 }
3038 } else {
3039 change = Some(Edit {
3040 old_bytes: self.old_offset..self.old_offset,
3041 new_bytes: self.new_offset..self.new_offset + fragment.len,
3042 old_lines: self.old_point..self.old_point,
3043 });
3044 }
3045
3046 self.new_offset += fragment.len;
3047 self.new_point += &fragment_lines;
3048 } else if fragment.was_visible(&self.since, &self.undos) && !fragment.visible {
3049 let deleted_start = cursor.start().deleted;
3050 let fragment_lines = self.deleted_text.to_point(deleted_start + fragment.len)
3051 - self.deleted_text.to_point(deleted_start);
3052 if let Some(ref mut change) = change {
3053 if change.new_bytes.end == self.new_offset {
3054 change.old_bytes.end += fragment.len;
3055 change.old_lines.end += &fragment_lines;
3056 } else {
3057 break;
3058 }
3059 } else {
3060 change = Some(Edit {
3061 old_bytes: self.old_offset..self.old_offset + fragment.len,
3062 new_bytes: self.new_offset..self.new_offset,
3063 old_lines: self.old_point..self.old_point + &fragment_lines,
3064 });
3065 }
3066
3067 self.old_offset += fragment.len;
3068 self.old_point += &fragment_lines;
3069 }
3070
3071 cursor.next(&None);
3072 }
3073
3074 change
3075 }
3076}
3077
3078struct ByteChunks<'a>(rope::Chunks<'a>);
3079
3080impl<'a> Iterator for ByteChunks<'a> {
3081 type Item = &'a [u8];
3082
3083 fn next(&mut self) -> Option<Self::Item> {
3084 self.0.next().map(str::as_bytes)
3085 }
3086}
3087
3088struct TextProvider<'a>(&'a Rope);
3089
3090impl<'a> tree_sitter::TextProvider<'a> for TextProvider<'a> {
3091 type I = ByteChunks<'a>;
3092
3093 fn text(&mut self, node: tree_sitter::Node) -> Self::I {
3094 ByteChunks(self.0.chunks_in_range(node.byte_range()))
3095 }
3096}
3097
3098struct Highlights<'a> {
3099 captures: tree_sitter::QueryCaptures<'a, 'a, TextProvider<'a>>,
3100 next_capture: Option<(tree_sitter::QueryMatch<'a, 'a>, usize)>,
3101 stack: Vec<(usize, HighlightId)>,
3102 highlight_map: HighlightMap,
3103}
3104
3105pub struct HighlightedChunks<'a> {
3106 range: Range<usize>,
3107 chunks: Chunks<'a>,
3108 highlights: Option<Highlights<'a>>,
3109}
3110
3111impl<'a> HighlightedChunks<'a> {
3112 pub fn seek(&mut self, offset: usize) {
3113 self.range.start = offset;
3114 self.chunks.seek(self.range.start);
3115 if let Some(highlights) = self.highlights.as_mut() {
3116 highlights
3117 .stack
3118 .retain(|(end_offset, _)| *end_offset > offset);
3119 if let Some((mat, capture_ix)) = &highlights.next_capture {
3120 let capture = mat.captures[*capture_ix as usize];
3121 if offset >= capture.node.start_byte() {
3122 let next_capture_end = capture.node.end_byte();
3123 if offset < next_capture_end {
3124 highlights.stack.push((
3125 next_capture_end,
3126 highlights.highlight_map.get(capture.index),
3127 ));
3128 }
3129 highlights.next_capture.take();
3130 }
3131 }
3132 highlights.captures.set_byte_range(self.range.clone());
3133 }
3134 }
3135
3136 pub fn offset(&self) -> usize {
3137 self.range.start
3138 }
3139}
3140
3141impl<'a> Iterator for HighlightedChunks<'a> {
3142 type Item = (&'a str, HighlightId);
3143
3144 fn next(&mut self) -> Option<Self::Item> {
3145 let mut next_capture_start = usize::MAX;
3146
3147 if let Some(highlights) = self.highlights.as_mut() {
3148 while let Some((parent_capture_end, _)) = highlights.stack.last() {
3149 if *parent_capture_end <= self.range.start {
3150 highlights.stack.pop();
3151 } else {
3152 break;
3153 }
3154 }
3155
3156 if highlights.next_capture.is_none() {
3157 highlights.next_capture = highlights.captures.next();
3158 }
3159
3160 while let Some((mat, capture_ix)) = highlights.next_capture.as_ref() {
3161 let capture = mat.captures[*capture_ix as usize];
3162 if self.range.start < capture.node.start_byte() {
3163 next_capture_start = capture.node.start_byte();
3164 break;
3165 } else {
3166 let style_id = highlights.highlight_map.get(capture.index);
3167 highlights.stack.push((capture.node.end_byte(), style_id));
3168 highlights.next_capture = highlights.captures.next();
3169 }
3170 }
3171 }
3172
3173 if let Some(chunk) = self.chunks.peek() {
3174 let chunk_start = self.range.start;
3175 let mut chunk_end = (self.chunks.offset() + chunk.len()).min(next_capture_start);
3176 let mut style_id = HighlightId::default();
3177 if let Some((parent_capture_end, parent_style_id)) =
3178 self.highlights.as_ref().and_then(|h| h.stack.last())
3179 {
3180 chunk_end = chunk_end.min(*parent_capture_end);
3181 style_id = *parent_style_id;
3182 }
3183
3184 let slice =
3185 &chunk[chunk_start - self.chunks.offset()..chunk_end - self.chunks.offset()];
3186 self.range.start = chunk_end;
3187 if self.range.start == self.chunks.offset() + chunk.len() {
3188 self.chunks.next().unwrap();
3189 }
3190
3191 Some((slice, style_id))
3192 } else {
3193 None
3194 }
3195 }
3196}
3197
3198impl Fragment {
3199 fn is_visible(&self, undos: &UndoMap) -> bool {
3200 !undos.is_undone(self.timestamp.local())
3201 && self.deletions.iter().all(|d| undos.is_undone(*d))
3202 }
3203
3204 fn was_visible(&self, version: &clock::Global, undos: &UndoMap) -> bool {
3205 (version.observed(self.timestamp.local())
3206 && !undos.was_undone(self.timestamp.local(), version))
3207 && self
3208 .deletions
3209 .iter()
3210 .all(|d| !version.observed(*d) || undos.was_undone(*d, version))
3211 }
3212}
3213
3214impl sum_tree::Item for Fragment {
3215 type Summary = FragmentSummary;
3216
3217 fn summary(&self) -> Self::Summary {
3218 let mut max_version = clock::Global::new();
3219 max_version.observe(self.timestamp.local());
3220 for deletion in &self.deletions {
3221 max_version.observe(*deletion);
3222 }
3223 max_version.join(&self.max_undos);
3224
3225 let mut min_insertion_version = clock::Global::new();
3226 min_insertion_version.observe(self.timestamp.local());
3227 let max_insertion_version = min_insertion_version.clone();
3228 if self.visible {
3229 FragmentSummary {
3230 text: FragmentTextSummary {
3231 visible: self.len,
3232 deleted: 0,
3233 },
3234 max_version,
3235 min_insertion_version,
3236 max_insertion_version,
3237 }
3238 } else {
3239 FragmentSummary {
3240 text: FragmentTextSummary {
3241 visible: 0,
3242 deleted: self.len,
3243 },
3244 max_version,
3245 min_insertion_version,
3246 max_insertion_version,
3247 }
3248 }
3249 }
3250}
3251
3252impl sum_tree::Summary for FragmentSummary {
3253 type Context = Option<clock::Global>;
3254
3255 fn add_summary(&mut self, other: &Self, _: &Self::Context) {
3256 self.text.visible += &other.text.visible;
3257 self.text.deleted += &other.text.deleted;
3258 self.max_version.join(&other.max_version);
3259 self.min_insertion_version
3260 .meet(&other.min_insertion_version);
3261 self.max_insertion_version
3262 .join(&other.max_insertion_version);
3263 }
3264}
3265
3266impl Default for FragmentSummary {
3267 fn default() -> Self {
3268 FragmentSummary {
3269 text: FragmentTextSummary::default(),
3270 max_version: clock::Global::new(),
3271 min_insertion_version: clock::Global::new(),
3272 max_insertion_version: clock::Global::new(),
3273 }
3274 }
3275}
3276
3277impl<'a> sum_tree::Dimension<'a, FragmentSummary> for usize {
3278 fn add_summary(&mut self, summary: &FragmentSummary, _: &Option<clock::Global>) {
3279 *self += summary.text.visible;
3280 }
3281}
3282
3283impl<'a> sum_tree::SeekTarget<'a, FragmentSummary, FragmentTextSummary> for usize {
3284 fn cmp(
3285 &self,
3286 cursor_location: &FragmentTextSummary,
3287 _: &Option<clock::Global>,
3288 ) -> cmp::Ordering {
3289 Ord::cmp(self, &cursor_location.visible)
3290 }
3291}
3292
3293#[derive(Copy, Clone, Debug, Eq, PartialEq)]
3294enum VersionedOffset {
3295 Offset(usize),
3296 InvalidVersion,
3297}
3298
3299impl VersionedOffset {
3300 fn offset(&self) -> usize {
3301 if let Self::Offset(offset) = self {
3302 *offset
3303 } else {
3304 panic!("invalid version")
3305 }
3306 }
3307}
3308
3309impl Default for VersionedOffset {
3310 fn default() -> Self {
3311 Self::Offset(0)
3312 }
3313}
3314
3315impl<'a> sum_tree::Dimension<'a, FragmentSummary> for VersionedOffset {
3316 fn add_summary(&mut self, summary: &'a FragmentSummary, cx: &Option<clock::Global>) {
3317 if let Self::Offset(offset) = self {
3318 let version = cx.as_ref().unwrap();
3319 if *version >= summary.max_insertion_version {
3320 *offset += summary.text.visible + summary.text.deleted;
3321 } else if !summary
3322 .min_insertion_version
3323 .iter()
3324 .all(|t| !version.observed(*t))
3325 {
3326 *self = Self::InvalidVersion;
3327 }
3328 }
3329 }
3330}
3331
3332impl<'a> sum_tree::SeekTarget<'a, FragmentSummary, Self> for VersionedOffset {
3333 fn cmp(&self, other: &Self, _: &Option<clock::Global>) -> cmp::Ordering {
3334 match (self, other) {
3335 (Self::Offset(a), Self::Offset(b)) => Ord::cmp(a, b),
3336 (Self::Offset(_), Self::InvalidVersion) => cmp::Ordering::Less,
3337 (Self::InvalidVersion, _) => unreachable!(),
3338 }
3339 }
3340}
3341
3342impl Operation {
3343 fn replica_id(&self) -> ReplicaId {
3344 self.lamport_timestamp().replica_id
3345 }
3346
3347 fn lamport_timestamp(&self) -> clock::Lamport {
3348 match self {
3349 Operation::Edit(edit) => edit.timestamp.lamport(),
3350 Operation::Undo {
3351 lamport_timestamp, ..
3352 } => *lamport_timestamp,
3353 Operation::UpdateSelections {
3354 lamport_timestamp, ..
3355 } => *lamport_timestamp,
3356 Operation::SetActiveSelections {
3357 lamport_timestamp, ..
3358 } => *lamport_timestamp,
3359 #[cfg(test)]
3360 Operation::Test(lamport_timestamp) => *lamport_timestamp,
3361 }
3362 }
3363
3364 pub fn is_edit(&self) -> bool {
3365 match self {
3366 Operation::Edit { .. } => true,
3367 _ => false,
3368 }
3369 }
3370}
3371
3372impl<'a> Into<proto::Operation> for &'a Operation {
3373 fn into(self) -> proto::Operation {
3374 proto::Operation {
3375 variant: Some(match self {
3376 Operation::Edit(edit) => proto::operation::Variant::Edit(edit.into()),
3377 Operation::Undo {
3378 undo,
3379 lamport_timestamp,
3380 } => proto::operation::Variant::Undo(proto::operation::Undo {
3381 replica_id: undo.id.replica_id as u32,
3382 local_timestamp: undo.id.value,
3383 lamport_timestamp: lamport_timestamp.value,
3384 ranges: undo
3385 .ranges
3386 .iter()
3387 .map(|r| proto::Range {
3388 start: r.start as u64,
3389 end: r.end as u64,
3390 })
3391 .collect(),
3392 counts: undo
3393 .counts
3394 .iter()
3395 .map(|(edit_id, count)| proto::operation::UndoCount {
3396 replica_id: edit_id.replica_id as u32,
3397 local_timestamp: edit_id.value,
3398 count: *count,
3399 })
3400 .collect(),
3401 version: From::from(&undo.version),
3402 }),
3403 Operation::UpdateSelections {
3404 set_id,
3405 selections,
3406 lamport_timestamp,
3407 } => proto::operation::Variant::UpdateSelections(
3408 proto::operation::UpdateSelections {
3409 replica_id: set_id.replica_id as u32,
3410 local_timestamp: set_id.value,
3411 lamport_timestamp: lamport_timestamp.value,
3412 set: selections.as_ref().map(|selections| proto::SelectionSet {
3413 selections: selections.iter().map(Into::into).collect(),
3414 }),
3415 },
3416 ),
3417 Operation::SetActiveSelections {
3418 set_id,
3419 lamport_timestamp,
3420 } => proto::operation::Variant::SetActiveSelections(
3421 proto::operation::SetActiveSelections {
3422 replica_id: lamport_timestamp.replica_id as u32,
3423 local_timestamp: set_id.map(|set_id| set_id.value),
3424 lamport_timestamp: lamport_timestamp.value,
3425 },
3426 ),
3427 #[cfg(test)]
3428 Operation::Test(_) => unimplemented!(),
3429 }),
3430 }
3431 }
3432}
3433
3434impl<'a> Into<proto::operation::Edit> for &'a EditOperation {
3435 fn into(self) -> proto::operation::Edit {
3436 let ranges = self
3437 .ranges
3438 .iter()
3439 .map(|range| proto::Range {
3440 start: range.start as u64,
3441 end: range.end as u64,
3442 })
3443 .collect();
3444 proto::operation::Edit {
3445 replica_id: self.timestamp.replica_id as u32,
3446 local_timestamp: self.timestamp.local,
3447 lamport_timestamp: self.timestamp.lamport,
3448 version: From::from(&self.version),
3449 ranges,
3450 new_text: self.new_text.clone(),
3451 }
3452 }
3453}
3454
3455impl<'a> Into<proto::Anchor> for &'a Anchor {
3456 fn into(self) -> proto::Anchor {
3457 proto::Anchor {
3458 version: (&self.version).into(),
3459 offset: self.offset as u64,
3460 bias: match self.bias {
3461 Bias::Left => proto::anchor::Bias::Left as i32,
3462 Bias::Right => proto::anchor::Bias::Right as i32,
3463 },
3464 }
3465 }
3466}
3467
3468impl<'a> Into<proto::Selection> for &'a Selection {
3469 fn into(self) -> proto::Selection {
3470 proto::Selection {
3471 id: self.id as u64,
3472 start: Some((&self.start).into()),
3473 end: Some((&self.end).into()),
3474 reversed: self.reversed,
3475 }
3476 }
3477}
3478
3479impl TryFrom<proto::Operation> for Operation {
3480 type Error = anyhow::Error;
3481
3482 fn try_from(message: proto::Operation) -> Result<Self, Self::Error> {
3483 Ok(
3484 match message
3485 .variant
3486 .ok_or_else(|| anyhow!("missing operation variant"))?
3487 {
3488 proto::operation::Variant::Edit(edit) => Operation::Edit(edit.into()),
3489 proto::operation::Variant::Undo(undo) => Operation::Undo {
3490 lamport_timestamp: clock::Lamport {
3491 replica_id: undo.replica_id as ReplicaId,
3492 value: undo.lamport_timestamp,
3493 },
3494 undo: UndoOperation {
3495 id: clock::Local {
3496 replica_id: undo.replica_id as ReplicaId,
3497 value: undo.local_timestamp,
3498 },
3499 counts: undo
3500 .counts
3501 .into_iter()
3502 .map(|c| {
3503 (
3504 clock::Local {
3505 replica_id: c.replica_id as ReplicaId,
3506 value: c.local_timestamp,
3507 },
3508 c.count,
3509 )
3510 })
3511 .collect(),
3512 ranges: undo
3513 .ranges
3514 .into_iter()
3515 .map(|r| r.start as usize..r.end as usize)
3516 .collect(),
3517 version: undo.version.into(),
3518 },
3519 },
3520 proto::operation::Variant::UpdateSelections(message) => {
3521 let selections: Option<Vec<Selection>> = if let Some(set) = message.set {
3522 Some(
3523 set.selections
3524 .into_iter()
3525 .map(TryFrom::try_from)
3526 .collect::<Result<_, _>>()?,
3527 )
3528 } else {
3529 None
3530 };
3531 Operation::UpdateSelections {
3532 set_id: clock::Lamport {
3533 replica_id: message.replica_id as ReplicaId,
3534 value: message.local_timestamp,
3535 },
3536 lamport_timestamp: clock::Lamport {
3537 replica_id: message.replica_id as ReplicaId,
3538 value: message.lamport_timestamp,
3539 },
3540 selections: selections.map(Arc::from),
3541 }
3542 }
3543 proto::operation::Variant::SetActiveSelections(message) => {
3544 Operation::SetActiveSelections {
3545 set_id: message.local_timestamp.map(|value| clock::Lamport {
3546 replica_id: message.replica_id as ReplicaId,
3547 value,
3548 }),
3549 lamport_timestamp: clock::Lamport {
3550 replica_id: message.replica_id as ReplicaId,
3551 value: message.lamport_timestamp,
3552 },
3553 }
3554 }
3555 },
3556 )
3557 }
3558}
3559
3560impl From<proto::operation::Edit> for EditOperation {
3561 fn from(edit: proto::operation::Edit) -> Self {
3562 let ranges = edit
3563 .ranges
3564 .into_iter()
3565 .map(|range| range.start as usize..range.end as usize)
3566 .collect();
3567 EditOperation {
3568 timestamp: InsertionTimestamp {
3569 replica_id: edit.replica_id as ReplicaId,
3570 local: edit.local_timestamp,
3571 lamport: edit.lamport_timestamp,
3572 },
3573 version: edit.version.into(),
3574 ranges,
3575 new_text: edit.new_text,
3576 }
3577 }
3578}
3579
3580impl TryFrom<proto::Anchor> for Anchor {
3581 type Error = anyhow::Error;
3582
3583 fn try_from(message: proto::Anchor) -> Result<Self, Self::Error> {
3584 let mut version = clock::Global::new();
3585 for entry in message.version {
3586 version.observe(clock::Local {
3587 replica_id: entry.replica_id as ReplicaId,
3588 value: entry.timestamp,
3589 });
3590 }
3591
3592 Ok(Self {
3593 offset: message.offset as usize,
3594 bias: if message.bias == proto::anchor::Bias::Left as i32 {
3595 Bias::Left
3596 } else if message.bias == proto::anchor::Bias::Right as i32 {
3597 Bias::Right
3598 } else {
3599 Err(anyhow!("invalid anchor bias {}", message.bias))?
3600 },
3601 version,
3602 })
3603 }
3604}
3605
3606impl TryFrom<proto::Selection> for Selection {
3607 type Error = anyhow::Error;
3608
3609 fn try_from(selection: proto::Selection) -> Result<Self, Self::Error> {
3610 Ok(Selection {
3611 id: selection.id as usize,
3612 start: selection
3613 .start
3614 .ok_or_else(|| anyhow!("missing selection start"))?
3615 .try_into()?,
3616 end: selection
3617 .end
3618 .ok_or_else(|| anyhow!("missing selection end"))?
3619 .try_into()?,
3620 reversed: selection.reversed,
3621 goal: SelectionGoal::None,
3622 })
3623 }
3624}
3625
3626pub trait ToOffset {
3627 fn to_offset<'a>(&self, content: impl Into<Content<'a>>) -> usize;
3628}
3629
3630impl ToOffset for Point {
3631 fn to_offset<'a>(&self, content: impl Into<Content<'a>>) -> usize {
3632 content.into().visible_text.to_offset(*self)
3633 }
3634}
3635
3636impl ToOffset for usize {
3637 fn to_offset<'a>(&self, _: impl Into<Content<'a>>) -> usize {
3638 *self
3639 }
3640}
3641
3642impl ToOffset for Anchor {
3643 fn to_offset<'a>(&self, content: impl Into<Content<'a>>) -> usize {
3644 content.into().summary_for_anchor(self).bytes
3645 }
3646}
3647
3648impl<'a> ToOffset for &'a Anchor {
3649 fn to_offset<'b>(&self, content: impl Into<Content<'b>>) -> usize {
3650 content.into().summary_for_anchor(self).bytes
3651 }
3652}
3653
3654pub trait ToPoint {
3655 fn to_point<'a>(&self, content: impl Into<Content<'a>>) -> Point;
3656}
3657
3658impl ToPoint for Anchor {
3659 fn to_point<'a>(&self, content: impl Into<Content<'a>>) -> Point {
3660 content.into().summary_for_anchor(self).lines
3661 }
3662}
3663
3664impl ToPoint for usize {
3665 fn to_point<'a>(&self, content: impl Into<Content<'a>>) -> Point {
3666 content.into().visible_text.to_point(*self)
3667 }
3668}
3669
3670fn contiguous_ranges(mut values: impl Iterator<Item = u32>) -> impl Iterator<Item = Range<u32>> {
3671 let mut current_range: Option<Range<u32>> = None;
3672 std::iter::from_fn(move || loop {
3673 if let Some(value) = values.next() {
3674 if let Some(range) = &mut current_range {
3675 if value == range.end {
3676 range.end += 1;
3677 continue;
3678 }
3679 }
3680
3681 let prev_range = current_range.clone();
3682 current_range = Some(value..(value + 1));
3683 if prev_range.is_some() {
3684 return prev_range;
3685 }
3686 } else {
3687 return current_range.take();
3688 }
3689 })
3690}
3691
3692#[cfg(test)]
3693mod tests {
3694 use crate::random_char_iter::RandomCharIter;
3695
3696 use super::*;
3697 use gpui::ModelHandle;
3698 use rand::prelude::*;
3699 use std::{cell::RefCell, cmp::Ordering, env, mem, rc::Rc};
3700
3701 #[gpui::test]
3702 fn test_edit(cx: &mut gpui::MutableAppContext) {
3703 cx.add_model(|cx| {
3704 let mut buffer = Buffer::new(0, "abc", cx);
3705 assert_eq!(buffer.text(), "abc");
3706 buffer.edit(vec![3..3], "def", cx);
3707 assert_eq!(buffer.text(), "abcdef");
3708 buffer.edit(vec![0..0], "ghi", cx);
3709 assert_eq!(buffer.text(), "ghiabcdef");
3710 buffer.edit(vec![5..5], "jkl", cx);
3711 assert_eq!(buffer.text(), "ghiabjklcdef");
3712 buffer.edit(vec![6..7], "", cx);
3713 assert_eq!(buffer.text(), "ghiabjlcdef");
3714 buffer.edit(vec![4..9], "mno", cx);
3715 assert_eq!(buffer.text(), "ghiamnoef");
3716 buffer
3717 });
3718 }
3719
3720 #[gpui::test]
3721 fn test_edit_events(cx: &mut gpui::MutableAppContext) {
3722 let mut now = Instant::now();
3723 let buffer_1_events = Rc::new(RefCell::new(Vec::new()));
3724 let buffer_2_events = Rc::new(RefCell::new(Vec::new()));
3725
3726 let buffer1 = cx.add_model(|cx| Buffer::new(0, "abcdef", cx));
3727 let buffer2 = cx.add_model(|cx| Buffer::new(1, "abcdef", cx));
3728 let buffer_ops = buffer1.update(cx, |buffer, cx| {
3729 let buffer_1_events = buffer_1_events.clone();
3730 cx.subscribe(&buffer1, move |_, _, event, _| {
3731 buffer_1_events.borrow_mut().push(event.clone())
3732 })
3733 .detach();
3734 let buffer_2_events = buffer_2_events.clone();
3735 cx.subscribe(&buffer2, move |_, _, event, _| {
3736 buffer_2_events.borrow_mut().push(event.clone())
3737 })
3738 .detach();
3739
3740 // An edit emits an edited event, followed by a dirtied event,
3741 // since the buffer was previously in a clean state.
3742 buffer.edit(Some(2..4), "XYZ", cx);
3743
3744 // An empty transaction does not emit any events.
3745 buffer.start_transaction(None).unwrap();
3746 buffer.end_transaction(None, cx).unwrap();
3747
3748 // A transaction containing two edits emits one edited event.
3749 now += Duration::from_secs(1);
3750 buffer.start_transaction_at(None, now).unwrap();
3751 buffer.edit(Some(5..5), "u", cx);
3752 buffer.edit(Some(6..6), "w", cx);
3753 buffer.end_transaction_at(None, now, cx).unwrap();
3754
3755 // Undoing a transaction emits one edited event.
3756 buffer.undo(cx);
3757
3758 buffer.operations.clone()
3759 });
3760
3761 // Incorporating a set of remote ops emits a single edited event,
3762 // followed by a dirtied event.
3763 buffer2.update(cx, |buffer, cx| {
3764 buffer.apply_ops(buffer_ops, cx).unwrap();
3765 });
3766
3767 let buffer_1_events = buffer_1_events.borrow();
3768 assert_eq!(
3769 *buffer_1_events,
3770 vec![Event::Edited, Event::Dirtied, Event::Edited, Event::Edited]
3771 );
3772
3773 let buffer_2_events = buffer_2_events.borrow();
3774 assert_eq!(*buffer_2_events, vec![Event::Edited, Event::Dirtied]);
3775 }
3776
3777 #[gpui::test(iterations = 100)]
3778 fn test_random_edits(cx: &mut gpui::MutableAppContext, mut rng: StdRng) {
3779 let operations = env::var("OPERATIONS")
3780 .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
3781 .unwrap_or(10);
3782
3783 let reference_string_len = rng.gen_range(0..3);
3784 let mut reference_string = RandomCharIter::new(&mut rng)
3785 .take(reference_string_len)
3786 .collect::<String>();
3787 cx.add_model(|cx| {
3788 let mut buffer = Buffer::new(0, reference_string.as_str(), cx);
3789 buffer.history.group_interval = Duration::from_millis(rng.gen_range(0..=200));
3790 let mut buffer_versions = Vec::new();
3791 log::info!(
3792 "buffer text {:?}, version: {:?}",
3793 buffer.text(),
3794 buffer.version()
3795 );
3796
3797 for _i in 0..operations {
3798 let (old_ranges, new_text) = buffer.randomly_mutate(&mut rng, cx);
3799 for old_range in old_ranges.iter().rev() {
3800 reference_string.replace_range(old_range.clone(), &new_text);
3801 }
3802 assert_eq!(buffer.text(), reference_string);
3803 log::info!(
3804 "buffer text {:?}, version: {:?}",
3805 buffer.text(),
3806 buffer.version()
3807 );
3808
3809 if rng.gen_bool(0.25) {
3810 buffer.randomly_undo_redo(&mut rng, cx);
3811 reference_string = buffer.text();
3812 log::info!(
3813 "buffer text {:?}, version: {:?}",
3814 buffer.text(),
3815 buffer.version()
3816 );
3817 }
3818
3819 let range = buffer.random_byte_range(0, &mut rng);
3820 assert_eq!(
3821 buffer.text_summary_for_range(range.clone()),
3822 TextSummary::from(&reference_string[range])
3823 );
3824
3825 if rng.gen_bool(0.3) {
3826 buffer_versions.push(buffer.clone());
3827 }
3828 }
3829
3830 for mut old_buffer in buffer_versions {
3831 let edits = buffer
3832 .edits_since(old_buffer.version.clone())
3833 .collect::<Vec<_>>();
3834
3835 log::info!(
3836 "mutating old buffer version {:?}, text: {:?}, edits since: {:?}",
3837 old_buffer.version(),
3838 old_buffer.text(),
3839 edits,
3840 );
3841
3842 let mut delta = 0_isize;
3843 for edit in edits {
3844 let old_start = (edit.old_bytes.start as isize + delta) as usize;
3845 let new_text: String = buffer.text_for_range(edit.new_bytes.clone()).collect();
3846 old_buffer.edit(
3847 Some(old_start..old_start + edit.deleted_bytes()),
3848 new_text,
3849 cx,
3850 );
3851 delta += edit.delta();
3852 }
3853 assert_eq!(old_buffer.text(), buffer.text());
3854 }
3855
3856 buffer
3857 });
3858 }
3859
3860 #[gpui::test]
3861 fn test_line_len(cx: &mut gpui::MutableAppContext) {
3862 cx.add_model(|cx| {
3863 let mut buffer = Buffer::new(0, "", cx);
3864 buffer.edit(vec![0..0], "abcd\nefg\nhij", cx);
3865 buffer.edit(vec![12..12], "kl\nmno", cx);
3866 buffer.edit(vec![18..18], "\npqrs\n", cx);
3867 buffer.edit(vec![18..21], "\nPQ", cx);
3868
3869 assert_eq!(buffer.line_len(0), 4);
3870 assert_eq!(buffer.line_len(1), 3);
3871 assert_eq!(buffer.line_len(2), 5);
3872 assert_eq!(buffer.line_len(3), 3);
3873 assert_eq!(buffer.line_len(4), 4);
3874 assert_eq!(buffer.line_len(5), 0);
3875 buffer
3876 });
3877 }
3878
3879 #[gpui::test]
3880 fn test_text_summary_for_range(cx: &mut gpui::MutableAppContext) {
3881 cx.add_model(|cx| {
3882 let buffer = Buffer::new(0, "ab\nefg\nhklm\nnopqrs\ntuvwxyz", cx);
3883 assert_eq!(
3884 buffer.text_summary_for_range(1..3),
3885 TextSummary {
3886 bytes: 2,
3887 lines: Point::new(1, 0),
3888 first_line_chars: 1,
3889 last_line_chars: 0,
3890 longest_row: 0,
3891 longest_row_chars: 1,
3892 }
3893 );
3894 assert_eq!(
3895 buffer.text_summary_for_range(1..12),
3896 TextSummary {
3897 bytes: 11,
3898 lines: Point::new(3, 0),
3899 first_line_chars: 1,
3900 last_line_chars: 0,
3901 longest_row: 2,
3902 longest_row_chars: 4,
3903 }
3904 );
3905 assert_eq!(
3906 buffer.text_summary_for_range(0..20),
3907 TextSummary {
3908 bytes: 20,
3909 lines: Point::new(4, 1),
3910 first_line_chars: 2,
3911 last_line_chars: 1,
3912 longest_row: 3,
3913 longest_row_chars: 6,
3914 }
3915 );
3916 assert_eq!(
3917 buffer.text_summary_for_range(0..22),
3918 TextSummary {
3919 bytes: 22,
3920 lines: Point::new(4, 3),
3921 first_line_chars: 2,
3922 last_line_chars: 3,
3923 longest_row: 3,
3924 longest_row_chars: 6,
3925 }
3926 );
3927 assert_eq!(
3928 buffer.text_summary_for_range(7..22),
3929 TextSummary {
3930 bytes: 15,
3931 lines: Point::new(2, 3),
3932 first_line_chars: 4,
3933 last_line_chars: 3,
3934 longest_row: 1,
3935 longest_row_chars: 6,
3936 }
3937 );
3938 buffer
3939 });
3940 }
3941
3942 #[gpui::test]
3943 fn test_chars_at(cx: &mut gpui::MutableAppContext) {
3944 cx.add_model(|cx| {
3945 let mut buffer = Buffer::new(0, "", cx);
3946 buffer.edit(vec![0..0], "abcd\nefgh\nij", cx);
3947 buffer.edit(vec![12..12], "kl\nmno", cx);
3948 buffer.edit(vec![18..18], "\npqrs", cx);
3949 buffer.edit(vec![18..21], "\nPQ", cx);
3950
3951 let chars = buffer.chars_at(Point::new(0, 0));
3952 assert_eq!(chars.collect::<String>(), "abcd\nefgh\nijkl\nmno\nPQrs");
3953
3954 let chars = buffer.chars_at(Point::new(1, 0));
3955 assert_eq!(chars.collect::<String>(), "efgh\nijkl\nmno\nPQrs");
3956
3957 let chars = buffer.chars_at(Point::new(2, 0));
3958 assert_eq!(chars.collect::<String>(), "ijkl\nmno\nPQrs");
3959
3960 let chars = buffer.chars_at(Point::new(3, 0));
3961 assert_eq!(chars.collect::<String>(), "mno\nPQrs");
3962
3963 let chars = buffer.chars_at(Point::new(4, 0));
3964 assert_eq!(chars.collect::<String>(), "PQrs");
3965
3966 // Regression test:
3967 let mut buffer = Buffer::new(0, "", cx);
3968 buffer.edit(vec![0..0], "[workspace]\nmembers = [\n \"xray_core\",\n \"xray_server\",\n \"xray_cli\",\n \"xray_wasm\",\n]\n", cx);
3969 buffer.edit(vec![60..60], "\n", cx);
3970
3971 let chars = buffer.chars_at(Point::new(6, 0));
3972 assert_eq!(chars.collect::<String>(), " \"xray_wasm\",\n]\n");
3973
3974 buffer
3975 });
3976 }
3977
3978 #[gpui::test]
3979 fn test_anchors(cx: &mut gpui::MutableAppContext) {
3980 cx.add_model(|cx| {
3981 let mut buffer = Buffer::new(0, "", cx);
3982 buffer.edit(vec![0..0], "abc", cx);
3983 let left_anchor = buffer.anchor_before(2);
3984 let right_anchor = buffer.anchor_after(2);
3985
3986 buffer.edit(vec![1..1], "def\n", cx);
3987 assert_eq!(buffer.text(), "adef\nbc");
3988 assert_eq!(left_anchor.to_offset(&buffer), 6);
3989 assert_eq!(right_anchor.to_offset(&buffer), 6);
3990 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
3991 assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 1 });
3992
3993 buffer.edit(vec![2..3], "", cx);
3994 assert_eq!(buffer.text(), "adf\nbc");
3995 assert_eq!(left_anchor.to_offset(&buffer), 5);
3996 assert_eq!(right_anchor.to_offset(&buffer), 5);
3997 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
3998 assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 1 });
3999
4000 buffer.edit(vec![5..5], "ghi\n", cx);
4001 assert_eq!(buffer.text(), "adf\nbghi\nc");
4002 assert_eq!(left_anchor.to_offset(&buffer), 5);
4003 assert_eq!(right_anchor.to_offset(&buffer), 9);
4004 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
4005 assert_eq!(right_anchor.to_point(&buffer), Point { row: 2, column: 0 });
4006
4007 buffer.edit(vec![7..9], "", cx);
4008 assert_eq!(buffer.text(), "adf\nbghc");
4009 assert_eq!(left_anchor.to_offset(&buffer), 5);
4010 assert_eq!(right_anchor.to_offset(&buffer), 7);
4011 assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 },);
4012 assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 3 });
4013
4014 // Ensure anchoring to a point is equivalent to anchoring to an offset.
4015 assert_eq!(
4016 buffer.anchor_before(Point { row: 0, column: 0 }),
4017 buffer.anchor_before(0)
4018 );
4019 assert_eq!(
4020 buffer.anchor_before(Point { row: 0, column: 1 }),
4021 buffer.anchor_before(1)
4022 );
4023 assert_eq!(
4024 buffer.anchor_before(Point { row: 0, column: 2 }),
4025 buffer.anchor_before(2)
4026 );
4027 assert_eq!(
4028 buffer.anchor_before(Point { row: 0, column: 3 }),
4029 buffer.anchor_before(3)
4030 );
4031 assert_eq!(
4032 buffer.anchor_before(Point { row: 1, column: 0 }),
4033 buffer.anchor_before(4)
4034 );
4035 assert_eq!(
4036 buffer.anchor_before(Point { row: 1, column: 1 }),
4037 buffer.anchor_before(5)
4038 );
4039 assert_eq!(
4040 buffer.anchor_before(Point { row: 1, column: 2 }),
4041 buffer.anchor_before(6)
4042 );
4043 assert_eq!(
4044 buffer.anchor_before(Point { row: 1, column: 3 }),
4045 buffer.anchor_before(7)
4046 );
4047 assert_eq!(
4048 buffer.anchor_before(Point { row: 1, column: 4 }),
4049 buffer.anchor_before(8)
4050 );
4051
4052 // Comparison between anchors.
4053 let anchor_at_offset_0 = buffer.anchor_before(0);
4054 let anchor_at_offset_1 = buffer.anchor_before(1);
4055 let anchor_at_offset_2 = buffer.anchor_before(2);
4056
4057 assert_eq!(
4058 anchor_at_offset_0
4059 .cmp(&anchor_at_offset_0, &buffer)
4060 .unwrap(),
4061 Ordering::Equal
4062 );
4063 assert_eq!(
4064 anchor_at_offset_1
4065 .cmp(&anchor_at_offset_1, &buffer)
4066 .unwrap(),
4067 Ordering::Equal
4068 );
4069 assert_eq!(
4070 anchor_at_offset_2
4071 .cmp(&anchor_at_offset_2, &buffer)
4072 .unwrap(),
4073 Ordering::Equal
4074 );
4075
4076 assert_eq!(
4077 anchor_at_offset_0
4078 .cmp(&anchor_at_offset_1, &buffer)
4079 .unwrap(),
4080 Ordering::Less
4081 );
4082 assert_eq!(
4083 anchor_at_offset_1
4084 .cmp(&anchor_at_offset_2, &buffer)
4085 .unwrap(),
4086 Ordering::Less
4087 );
4088 assert_eq!(
4089 anchor_at_offset_0
4090 .cmp(&anchor_at_offset_2, &buffer)
4091 .unwrap(),
4092 Ordering::Less
4093 );
4094
4095 assert_eq!(
4096 anchor_at_offset_1
4097 .cmp(&anchor_at_offset_0, &buffer)
4098 .unwrap(),
4099 Ordering::Greater
4100 );
4101 assert_eq!(
4102 anchor_at_offset_2
4103 .cmp(&anchor_at_offset_1, &buffer)
4104 .unwrap(),
4105 Ordering::Greater
4106 );
4107 assert_eq!(
4108 anchor_at_offset_2
4109 .cmp(&anchor_at_offset_0, &buffer)
4110 .unwrap(),
4111 Ordering::Greater
4112 );
4113 buffer
4114 });
4115 }
4116
4117 #[gpui::test]
4118 fn test_anchors_at_start_and_end(cx: &mut gpui::MutableAppContext) {
4119 cx.add_model(|cx| {
4120 let mut buffer = Buffer::new(0, "", cx);
4121 let before_start_anchor = buffer.anchor_before(0);
4122 let after_end_anchor = buffer.anchor_after(0);
4123
4124 buffer.edit(vec![0..0], "abc", cx);
4125 assert_eq!(buffer.text(), "abc");
4126 assert_eq!(before_start_anchor.to_offset(&buffer), 0);
4127 assert_eq!(after_end_anchor.to_offset(&buffer), 3);
4128
4129 let after_start_anchor = buffer.anchor_after(0);
4130 let before_end_anchor = buffer.anchor_before(3);
4131
4132 buffer.edit(vec![3..3], "def", cx);
4133 buffer.edit(vec![0..0], "ghi", cx);
4134 assert_eq!(buffer.text(), "ghiabcdef");
4135 assert_eq!(before_start_anchor.to_offset(&buffer), 0);
4136 assert_eq!(after_start_anchor.to_offset(&buffer), 3);
4137 assert_eq!(before_end_anchor.to_offset(&buffer), 6);
4138 assert_eq!(after_end_anchor.to_offset(&buffer), 9);
4139 buffer
4140 });
4141 }
4142
4143 #[gpui::test]
4144 async fn test_apply_diff(mut cx: gpui::TestAppContext) {
4145 let text = "a\nbb\nccc\ndddd\neeeee\nffffff\n";
4146 let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
4147
4148 let text = "a\nccc\ndddd\nffffff\n";
4149 let diff = buffer.read_with(&cx, |b, cx| b.diff(text.into(), cx)).await;
4150 buffer.update(&mut cx, |b, cx| b.apply_diff(diff, cx));
4151 cx.read(|cx| assert_eq!(buffer.read(cx).text(), text));
4152
4153 let text = "a\n1\n\nccc\ndd2dd\nffffff\n";
4154 let diff = buffer.read_with(&cx, |b, cx| b.diff(text.into(), cx)).await;
4155 buffer.update(&mut cx, |b, cx| b.apply_diff(diff, cx));
4156 cx.read(|cx| assert_eq!(buffer.read(cx).text(), text));
4157 }
4158
4159 #[gpui::test]
4160 fn test_undo_redo(cx: &mut gpui::MutableAppContext) {
4161 cx.add_model(|cx| {
4162 let mut buffer = Buffer::new(0, "1234", cx);
4163 // Set group interval to zero so as to not group edits in the undo stack.
4164 buffer.history.group_interval = Duration::from_secs(0);
4165
4166 buffer.edit(vec![1..1], "abx", cx);
4167 buffer.edit(vec![3..4], "yzef", cx);
4168 buffer.edit(vec![3..5], "cd", cx);
4169 assert_eq!(buffer.text(), "1abcdef234");
4170
4171 let transactions = buffer.history.undo_stack.clone();
4172 assert_eq!(transactions.len(), 3);
4173
4174 buffer.undo_or_redo(transactions[0].clone(), cx).unwrap();
4175 assert_eq!(buffer.text(), "1cdef234");
4176 buffer.undo_or_redo(transactions[0].clone(), cx).unwrap();
4177 assert_eq!(buffer.text(), "1abcdef234");
4178
4179 buffer.undo_or_redo(transactions[1].clone(), cx).unwrap();
4180 assert_eq!(buffer.text(), "1abcdx234");
4181 buffer.undo_or_redo(transactions[2].clone(), cx).unwrap();
4182 assert_eq!(buffer.text(), "1abx234");
4183 buffer.undo_or_redo(transactions[1].clone(), cx).unwrap();
4184 assert_eq!(buffer.text(), "1abyzef234");
4185 buffer.undo_or_redo(transactions[2].clone(), cx).unwrap();
4186 assert_eq!(buffer.text(), "1abcdef234");
4187
4188 buffer.undo_or_redo(transactions[2].clone(), cx).unwrap();
4189 assert_eq!(buffer.text(), "1abyzef234");
4190 buffer.undo_or_redo(transactions[0].clone(), cx).unwrap();
4191 assert_eq!(buffer.text(), "1yzef234");
4192 buffer.undo_or_redo(transactions[1].clone(), cx).unwrap();
4193 assert_eq!(buffer.text(), "1234");
4194
4195 buffer
4196 });
4197 }
4198
4199 #[gpui::test]
4200 fn test_history(cx: &mut gpui::MutableAppContext) {
4201 cx.add_model(|cx| {
4202 let mut now = Instant::now();
4203 let mut buffer = Buffer::new(0, "123456", cx);
4204
4205 let set_id =
4206 buffer.add_selection_set(buffer.selections_from_ranges(vec![4..4]).unwrap(), cx);
4207 buffer.start_transaction_at(Some(set_id), now).unwrap();
4208 buffer.edit(vec![2..4], "cd", cx);
4209 buffer.end_transaction_at(Some(set_id), now, cx).unwrap();
4210 assert_eq!(buffer.text(), "12cd56");
4211 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![4..4]);
4212
4213 buffer.start_transaction_at(Some(set_id), now).unwrap();
4214 buffer
4215 .update_selection_set(
4216 set_id,
4217 buffer.selections_from_ranges(vec![1..3]).unwrap(),
4218 cx,
4219 )
4220 .unwrap();
4221 buffer.edit(vec![4..5], "e", cx);
4222 buffer.end_transaction_at(Some(set_id), now, cx).unwrap();
4223 assert_eq!(buffer.text(), "12cde6");
4224 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
4225
4226 now += buffer.history.group_interval + Duration::from_millis(1);
4227 buffer.start_transaction_at(Some(set_id), now).unwrap();
4228 buffer
4229 .update_selection_set(
4230 set_id,
4231 buffer.selections_from_ranges(vec![2..2]).unwrap(),
4232 cx,
4233 )
4234 .unwrap();
4235 buffer.edit(vec![0..1], "a", cx);
4236 buffer.edit(vec![1..1], "b", cx);
4237 buffer.end_transaction_at(Some(set_id), now, cx).unwrap();
4238 assert_eq!(buffer.text(), "ab2cde6");
4239 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![3..3]);
4240
4241 // Last transaction happened past the group interval, undo it on its
4242 // own.
4243 buffer.undo(cx);
4244 assert_eq!(buffer.text(), "12cde6");
4245 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
4246
4247 // First two transactions happened within the group interval, undo them
4248 // together.
4249 buffer.undo(cx);
4250 assert_eq!(buffer.text(), "123456");
4251 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![4..4]);
4252
4253 // Redo the first two transactions together.
4254 buffer.redo(cx);
4255 assert_eq!(buffer.text(), "12cde6");
4256 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
4257
4258 // Redo the last transaction on its own.
4259 buffer.redo(cx);
4260 assert_eq!(buffer.text(), "ab2cde6");
4261 assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![3..3]);
4262
4263 buffer.start_transaction_at(None, now).unwrap();
4264 buffer.end_transaction_at(None, now, cx).unwrap();
4265 buffer.undo(cx);
4266 assert_eq!(buffer.text(), "12cde6");
4267
4268 buffer
4269 });
4270 }
4271
4272 #[gpui::test]
4273 fn test_concurrent_edits(cx: &mut gpui::MutableAppContext) {
4274 let text = "abcdef";
4275
4276 let buffer1 = cx.add_model(|cx| Buffer::new(1, text, cx));
4277 let buffer2 = cx.add_model(|cx| Buffer::new(2, text, cx));
4278 let buffer3 = cx.add_model(|cx| Buffer::new(3, text, cx));
4279
4280 let buf1_op = buffer1.update(cx, |buffer, cx| {
4281 buffer.edit(vec![1..2], "12", cx);
4282 assert_eq!(buffer.text(), "a12cdef");
4283 buffer.operations.last().unwrap().clone()
4284 });
4285 let buf2_op = buffer2.update(cx, |buffer, cx| {
4286 buffer.edit(vec![3..4], "34", cx);
4287 assert_eq!(buffer.text(), "abc34ef");
4288 buffer.operations.last().unwrap().clone()
4289 });
4290 let buf3_op = buffer3.update(cx, |buffer, cx| {
4291 buffer.edit(vec![5..6], "56", cx);
4292 assert_eq!(buffer.text(), "abcde56");
4293 buffer.operations.last().unwrap().clone()
4294 });
4295
4296 buffer1.update(cx, |buffer, _| {
4297 buffer.apply_op(buf2_op.clone()).unwrap();
4298 buffer.apply_op(buf3_op.clone()).unwrap();
4299 });
4300 buffer2.update(cx, |buffer, _| {
4301 buffer.apply_op(buf1_op.clone()).unwrap();
4302 buffer.apply_op(buf3_op.clone()).unwrap();
4303 });
4304 buffer3.update(cx, |buffer, _| {
4305 buffer.apply_op(buf1_op.clone()).unwrap();
4306 buffer.apply_op(buf2_op.clone()).unwrap();
4307 });
4308
4309 assert_eq!(buffer1.read(cx).text(), "a12c34e56");
4310 assert_eq!(buffer2.read(cx).text(), "a12c34e56");
4311 assert_eq!(buffer3.read(cx).text(), "a12c34e56");
4312 }
4313
4314 #[gpui::test(iterations = 100)]
4315 fn test_random_concurrent_edits(cx: &mut gpui::MutableAppContext, mut rng: StdRng) {
4316 let peers = env::var("PEERS")
4317 .map(|i| i.parse().expect("invalid `PEERS` variable"))
4318 .unwrap_or(5);
4319 let operations = env::var("OPERATIONS")
4320 .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
4321 .unwrap_or(10);
4322
4323 let base_text_len = rng.gen_range(0..10);
4324 let base_text = RandomCharIter::new(&mut rng)
4325 .take(base_text_len)
4326 .collect::<String>();
4327 let mut replica_ids = Vec::new();
4328 let mut buffers = Vec::new();
4329 let mut network = Network::new(rng.clone());
4330
4331 for i in 0..peers {
4332 let buffer = cx.add_model(|cx| {
4333 let mut buf = Buffer::new(i as ReplicaId, base_text.as_str(), cx);
4334 buf.history.group_interval = Duration::from_millis(rng.gen_range(0..=200));
4335 buf
4336 });
4337 buffers.push(buffer);
4338 replica_ids.push(i as u16);
4339 network.add_peer(i as u16);
4340 }
4341
4342 log::info!("initial text: {:?}", base_text);
4343
4344 let mut mutation_count = operations;
4345 loop {
4346 let replica_index = rng.gen_range(0..peers);
4347 let replica_id = replica_ids[replica_index];
4348 buffers[replica_index].update(cx, |buffer, cx| match rng.gen_range(0..=100) {
4349 0..=50 if mutation_count != 0 => {
4350 buffer.randomly_mutate(&mut rng, cx);
4351 network.broadcast(buffer.replica_id, mem::take(&mut buffer.operations));
4352 log::info!("buffer {} text: {:?}", buffer.replica_id, buffer.text());
4353 mutation_count -= 1;
4354 }
4355 51..=70 if mutation_count != 0 => {
4356 buffer.randomly_undo_redo(&mut rng, cx);
4357 network.broadcast(buffer.replica_id, mem::take(&mut buffer.operations));
4358 mutation_count -= 1;
4359 }
4360 71..=100 if network.has_unreceived(replica_id) => {
4361 let ops = network.receive(replica_id);
4362 if !ops.is_empty() {
4363 log::info!(
4364 "peer {} applying {} ops from the network.",
4365 replica_id,
4366 ops.len()
4367 );
4368 buffer.apply_ops(ops, cx).unwrap();
4369 }
4370 }
4371 _ => {}
4372 });
4373
4374 if mutation_count == 0 && network.is_idle() {
4375 break;
4376 }
4377 }
4378
4379 let first_buffer = buffers[0].read(cx);
4380 for buffer in &buffers[1..] {
4381 let buffer = buffer.read(cx);
4382 assert_eq!(
4383 buffer.text(),
4384 first_buffer.text(),
4385 "Replica {} text != Replica 0 text",
4386 buffer.replica_id
4387 );
4388 assert_eq!(
4389 buffer.selection_sets().collect::<HashMap<_, _>>(),
4390 first_buffer.selection_sets().collect::<HashMap<_, _>>()
4391 );
4392 assert_eq!(
4393 buffer.all_selection_ranges().collect::<HashMap<_, _>>(),
4394 first_buffer
4395 .all_selection_ranges()
4396 .collect::<HashMap<_, _>>()
4397 );
4398 }
4399 }
4400
4401 #[gpui::test]
4402 async fn test_reparse(mut cx: gpui::TestAppContext) {
4403 let rust_lang = rust_lang();
4404 let buffer = cx.add_model(|cx| {
4405 let text = "fn a() {}".into();
4406 Buffer::from_history(0, History::new(text), None, Some(rust_lang.clone()), cx)
4407 });
4408
4409 // Wait for the initial text to parse
4410 buffer
4411 .condition(&cx, |buffer, _| !buffer.is_parsing())
4412 .await;
4413 assert_eq!(
4414 get_tree_sexp(&buffer, &cx),
4415 concat!(
4416 "(source_file (function_item name: (identifier) ",
4417 "parameters: (parameters) ",
4418 "body: (block)))"
4419 )
4420 );
4421
4422 buffer.update(&mut cx, |buffer, _| {
4423 buffer.set_sync_parse_timeout(Duration::ZERO)
4424 });
4425
4426 // Perform some edits (add parameter and variable reference)
4427 // Parsing doesn't begin until the transaction is complete
4428 buffer.update(&mut cx, |buf, cx| {
4429 buf.start_transaction(None).unwrap();
4430
4431 let offset = buf.text().find(")").unwrap();
4432 buf.edit(vec![offset..offset], "b: C", cx);
4433 assert!(!buf.is_parsing());
4434
4435 let offset = buf.text().find("}").unwrap();
4436 buf.edit(vec![offset..offset], " d; ", cx);
4437 assert!(!buf.is_parsing());
4438
4439 buf.end_transaction(None, cx).unwrap();
4440 assert_eq!(buf.text(), "fn a(b: C) { d; }");
4441 assert!(buf.is_parsing());
4442 });
4443 buffer
4444 .condition(&cx, |buffer, _| !buffer.is_parsing())
4445 .await;
4446 assert_eq!(
4447 get_tree_sexp(&buffer, &cx),
4448 concat!(
4449 "(source_file (function_item name: (identifier) ",
4450 "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
4451 "body: (block (identifier))))"
4452 )
4453 );
4454
4455 // Perform a series of edits without waiting for the current parse to complete:
4456 // * turn identifier into a field expression
4457 // * turn field expression into a method call
4458 // * add a turbofish to the method call
4459 buffer.update(&mut cx, |buf, cx| {
4460 let offset = buf.text().find(";").unwrap();
4461 buf.edit(vec![offset..offset], ".e", cx);
4462 assert_eq!(buf.text(), "fn a(b: C) { d.e; }");
4463 assert!(buf.is_parsing());
4464 });
4465 buffer.update(&mut cx, |buf, cx| {
4466 let offset = buf.text().find(";").unwrap();
4467 buf.edit(vec![offset..offset], "(f)", cx);
4468 assert_eq!(buf.text(), "fn a(b: C) { d.e(f); }");
4469 assert!(buf.is_parsing());
4470 });
4471 buffer.update(&mut cx, |buf, cx| {
4472 let offset = buf.text().find("(f)").unwrap();
4473 buf.edit(vec![offset..offset], "::<G>", cx);
4474 assert_eq!(buf.text(), "fn a(b: C) { d.e::<G>(f); }");
4475 assert!(buf.is_parsing());
4476 });
4477 buffer
4478 .condition(&cx, |buffer, _| !buffer.is_parsing())
4479 .await;
4480 assert_eq!(
4481 get_tree_sexp(&buffer, &cx),
4482 concat!(
4483 "(source_file (function_item name: (identifier) ",
4484 "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
4485 "body: (block (call_expression ",
4486 "function: (generic_function ",
4487 "function: (field_expression value: (identifier) field: (field_identifier)) ",
4488 "type_arguments: (type_arguments (type_identifier))) ",
4489 "arguments: (arguments (identifier))))))",
4490 )
4491 );
4492
4493 buffer.update(&mut cx, |buf, cx| {
4494 buf.undo(cx);
4495 assert_eq!(buf.text(), "fn a() {}");
4496 assert!(buf.is_parsing());
4497 });
4498 buffer
4499 .condition(&cx, |buffer, _| !buffer.is_parsing())
4500 .await;
4501 assert_eq!(
4502 get_tree_sexp(&buffer, &cx),
4503 concat!(
4504 "(source_file (function_item name: (identifier) ",
4505 "parameters: (parameters) ",
4506 "body: (block)))"
4507 )
4508 );
4509
4510 buffer.update(&mut cx, |buf, cx| {
4511 buf.redo(cx);
4512 assert_eq!(buf.text(), "fn a(b: C) { d.e::<G>(f); }");
4513 assert!(buf.is_parsing());
4514 });
4515 buffer
4516 .condition(&cx, |buffer, _| !buffer.is_parsing())
4517 .await;
4518 assert_eq!(
4519 get_tree_sexp(&buffer, &cx),
4520 concat!(
4521 "(source_file (function_item name: (identifier) ",
4522 "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
4523 "body: (block (call_expression ",
4524 "function: (generic_function ",
4525 "function: (field_expression value: (identifier) field: (field_identifier)) ",
4526 "type_arguments: (type_arguments (type_identifier))) ",
4527 "arguments: (arguments (identifier))))))",
4528 )
4529 );
4530
4531 fn get_tree_sexp(buffer: &ModelHandle<Buffer>, cx: &gpui::TestAppContext) -> String {
4532 buffer.read_with(cx, |buffer, _| {
4533 buffer.syntax_tree().unwrap().root_node().to_sexp()
4534 })
4535 }
4536 }
4537
4538 #[gpui::test]
4539 async fn test_enclosing_bracket_ranges(mut cx: gpui::TestAppContext) {
4540 use unindent::Unindent as _;
4541
4542 let rust_lang = rust_lang();
4543 let buffer = cx.add_model(|cx| {
4544 let text = "
4545 mod x {
4546 mod y {
4547
4548 }
4549 }
4550 "
4551 .unindent()
4552 .into();
4553 Buffer::from_history(0, History::new(text), None, Some(rust_lang.clone()), cx)
4554 });
4555 buffer
4556 .condition(&cx, |buffer, _| !buffer.is_parsing())
4557 .await;
4558 buffer.read_with(&cx, |buf, _| {
4559 assert_eq!(
4560 buf.enclosing_bracket_point_ranges(Point::new(1, 6)..Point::new(1, 6)),
4561 Some((
4562 Point::new(0, 6)..Point::new(0, 7),
4563 Point::new(4, 0)..Point::new(4, 1)
4564 ))
4565 );
4566 assert_eq!(
4567 buf.enclosing_bracket_point_ranges(Point::new(1, 10)..Point::new(1, 10)),
4568 Some((
4569 Point::new(1, 10)..Point::new(1, 11),
4570 Point::new(3, 4)..Point::new(3, 5)
4571 ))
4572 );
4573 assert_eq!(
4574 buf.enclosing_bracket_point_ranges(Point::new(3, 5)..Point::new(3, 5)),
4575 Some((
4576 Point::new(1, 10)..Point::new(1, 11),
4577 Point::new(3, 4)..Point::new(3, 5)
4578 ))
4579 );
4580 });
4581 }
4582
4583 #[gpui::test]
4584 async fn test_edit_with_autoindent(mut cx: gpui::TestAppContext) {
4585 let rust_lang = rust_lang();
4586 let buffer = cx.add_model(|cx| {
4587 let text = "fn a() {}".into();
4588 Buffer::from_history(0, History::new(text), None, Some(rust_lang.clone()), cx)
4589 });
4590
4591 buffer
4592 .condition(&cx, |buffer, _| !buffer.is_parsing())
4593 .await;
4594
4595 buffer.update(&mut cx, |buffer, cx| {
4596 buffer.edit_with_autoindent([8..8], "\n\n", cx);
4597 assert_eq!(buffer.text(), "fn a() {\n \n}");
4598
4599 buffer.edit_with_autoindent([Point::new(1, 4)..Point::new(1, 4)], "b()\n", cx);
4600 assert_eq!(buffer.text(), "fn a() {\n b()\n \n}");
4601
4602 buffer.edit_with_autoindent([Point::new(2, 4)..Point::new(2, 4)], ".c", cx);
4603 assert_eq!(buffer.text(), "fn a() {\n b()\n .c\n}");
4604 });
4605 }
4606
4607 #[test]
4608 fn test_contiguous_ranges() {
4609 assert_eq!(
4610 contiguous_ranges([1, 2, 3, 5, 6, 9, 10, 11, 12].iter().copied()).collect::<Vec<_>>(),
4611 &[1..4, 5..7, 9..13]
4612 );
4613 }
4614
4615 #[derive(Clone)]
4616 struct Envelope<T: Clone> {
4617 message: T,
4618 sender: ReplicaId,
4619 }
4620
4621 struct Network<T: Clone, R: rand::Rng> {
4622 inboxes: std::collections::BTreeMap<ReplicaId, Vec<Envelope<T>>>,
4623 all_messages: Vec<T>,
4624 rng: R,
4625 }
4626
4627 impl<T: Clone, R: rand::Rng> Network<T, R> {
4628 fn new(rng: R) -> Self {
4629 Network {
4630 inboxes: Default::default(),
4631 all_messages: Vec::new(),
4632 rng,
4633 }
4634 }
4635
4636 fn add_peer(&mut self, id: ReplicaId) {
4637 self.inboxes.insert(id, Vec::new());
4638 }
4639
4640 fn is_idle(&self) -> bool {
4641 self.inboxes.values().all(|i| i.is_empty())
4642 }
4643
4644 fn broadcast(&mut self, sender: ReplicaId, messages: Vec<T>) {
4645 for (replica, inbox) in self.inboxes.iter_mut() {
4646 if *replica != sender {
4647 for message in &messages {
4648 let min_index = inbox
4649 .iter()
4650 .enumerate()
4651 .rev()
4652 .find_map(|(index, envelope)| {
4653 if sender == envelope.sender {
4654 Some(index + 1)
4655 } else {
4656 None
4657 }
4658 })
4659 .unwrap_or(0);
4660
4661 // Insert one or more duplicates of this message *after* the previous
4662 // message delivered by this replica.
4663 for _ in 0..self.rng.gen_range(1..4) {
4664 let insertion_index = self.rng.gen_range(min_index..inbox.len() + 1);
4665 inbox.insert(
4666 insertion_index,
4667 Envelope {
4668 message: message.clone(),
4669 sender,
4670 },
4671 );
4672 }
4673 }
4674 }
4675 }
4676 self.all_messages.extend(messages);
4677 }
4678
4679 fn has_unreceived(&self, receiver: ReplicaId) -> bool {
4680 !self.inboxes[&receiver].is_empty()
4681 }
4682
4683 fn receive(&mut self, receiver: ReplicaId) -> Vec<T> {
4684 let inbox = self.inboxes.get_mut(&receiver).unwrap();
4685 let count = self.rng.gen_range(0..inbox.len() + 1);
4686 inbox
4687 .drain(0..count)
4688 .map(|envelope| envelope.message)
4689 .collect()
4690 }
4691 }
4692
4693 fn rust_lang() -> Arc<Language> {
4694 Arc::new(
4695 Language::new(
4696 LanguageConfig {
4697 name: "Rust".to_string(),
4698 path_suffixes: vec!["rs".to_string()],
4699 ..Default::default()
4700 },
4701 tree_sitter_rust::language(),
4702 )
4703 .with_indents_query(
4704 r#"
4705 (call_expression) @indent
4706 (field_expression) @indent
4707 (_ "{" "}" @end) @indent
4708 "#,
4709 )
4710 .unwrap()
4711 .with_brackets_query(r#" ("{" @open "}" @close) "#)
4712 .unwrap(),
4713 )
4714 }
4715}