1use {
2 crate::{
3 char::CharExt,
4 decoration::{Decoration, DecorationSet},
5 history::{EditKind, History},
6 inlays::{BlockInlay, InlineInlay},
7 iter::IteratorExt,
8 selection::SelectionSet,
9 session::SessionId,
10 settings::Settings,
11 str::StrExt,
12 text::{Change, Drift, Edit, Length, Position, Text},
13 token::{Token, TokenKind},
14 tokenizer::Tokenizer,
15 },
16 std::{
17 cell::{Ref, RefCell},
18 cmp::Ordering,
19 collections::HashMap,
20 iter,
21 ops::Range,
22 rc::Rc,
23 sync::mpsc::Sender,
24 },
25};
26
27#[derive(Clone, Debug)]
28pub struct CodeDocument(Rc<DocumentInner>);
29
30impl CodeDocument {
31 pub fn new(text: Text, decorations: DecorationSet) -> Self {
32 let line_count = text.as_lines().len();
33 let tokens: Vec<_> = (0..line_count)
34 .map(|line| tokenize(&text.as_lines()[line]).collect::<Vec<_>>())
35 .collect();
36 let inner = Self(Rc::new(DocumentInner {
37 history: RefCell::new(History::from(text)),
38 layout: RefCell::new(DocumentLayout {
39 indent_state: (0..line_count).map(|_| None).collect(),
40 tokens,
41 inline_inlays: (0..line_count).map(|_| Vec::new()).collect(),
42 block_inlays: Vec::new(),
43 }),
44 tokenizer: RefCell::new(Tokenizer::new(line_count)),
45 decorations: RefCell::new(decorations),
46 edit_senders: RefCell::new(HashMap::new()),
47 }));
48 inner.update_indent_state();
49 inner.0.tokenizer.borrow_mut().update(
50 &inner.0.history.borrow().as_text(),
51 &mut inner.0.layout.borrow_mut().tokens,
52 );
53 inner
54 }
55
56 pub fn replace(&self, new_text: Text) {
57 let mut history = self.0.history.borrow_mut();
58
59 let text_length = history.as_text().length();
61 let delete_edit = Edit {
62 change: Change::Delete(Position::zero(), text_length),
63 drift: Drift::Before,
64 };
65
66 let insert_edit = Edit {
68 change: Change::Insert(Position::zero(), new_text),
69 drift: Drift::Before,
70 };
71
72 history.force_new_group(); history.push_or_extend_group(SessionId::default(), EditKind::Other, &SelectionSet::default());
75 history.apply_edit(delete_edit.clone());
76 history.apply_edit(insert_edit.clone());
77
78 drop(history);
79
80 let edits = vec![delete_edit, insert_edit];
82 self.update_after_edit(None, None, &edits);
83 }
84
85 pub fn as_text(&self) -> Ref<'_, Text> {
86 Ref::map(self.0.history.borrow(), |history| history.as_text())
87 }
88
89 pub fn layout(&self) -> Ref<'_, DocumentLayout> {
90 self.0.layout.borrow()
91 }
92
93 pub fn decorations(&self) -> Ref<'_, [Decoration]> {
94 Ref::map(self.0.decorations.borrow(), |decorations| {
95 decorations.as_decorations()
96 })
97 }
98
99 pub fn edit_selections(
100 &self,
101 session_id: SessionId,
102 kind: EditKind,
103 selections: &SelectionSet,
104 settings: &Settings,
105 mut f: impl FnMut(Editor<'_>, Position, Length),
106 ) {
107 let mut history = self.0.history.borrow_mut();
108 history.push_or_extend_group(session_id, kind, selections);
109 let mut edits = Vec::new();
110 let mut line_ranges = Vec::new();
111 let mut prev_start = Position::zero();
112 let mut prev_adjusted_start = Position::zero();
113 let mut prev_edit_start = 0;
114 for &selection in selections {
115 let mut adjusted_start = prev_adjusted_start + (selection.start() - prev_start);
116 for edit in &edits[prev_edit_start..] {
117 adjusted_start = adjusted_start.apply_edit(edit);
118 }
119 let edit_start = edits.len();
120 f(
121 Editor {
122 history: &mut *history,
123 edits: &mut edits,
124 },
125 adjusted_start,
126 selection.length(),
127 );
128 for edit in &edits[edit_start..] {
129 match edit.change {
130 Change::Insert(position, ref text) => {
131 if let Some(char) = text.to_single_char() {
132 if char == '}'
133 && history.as_text().as_lines()[position.line_index]
134 [..position.byte_index]
135 .chars()
136 .all(|char| char.is_whitespace())
137 {
138 line_ranges.push(Range {
139 start: position.line_index,
140 end: position.line_index + 1,
141 });
142 }
143 } else if text.as_lines().len() > 1 {
144 line_ranges.push(Range {
145 start: if history.as_text().as_lines()[position.line_index]
146 [..position.byte_index]
147 .chars()
148 .all(|char| char.is_whitespace())
149 {
150 position.line_index
151 } else {
152 position.line_index + 1
153 },
154 end: position.line_index + text.as_lines().len(),
155 });
156 }
157 }
158 _ => {}
159 }
160 }
161 prev_start = selection.start();
162 prev_adjusted_start = adjusted_start;
163 prev_edit_start = edit_start;
164 }
165 drop(history);
166 self.autoindent(&line_ranges, settings.tab_column_count, &mut edits);
167 self.update_after_edit(Some(session_id), None, &edits);
168 }
169
170 pub fn edit_linewise(
171 &self,
172 origin_id: SessionId,
173 kind: EditKind,
174 selections: &SelectionSet,
175 mut f: impl FnMut(Editor, usize),
176 ) {
177 let mut history = self.0.history.borrow_mut();
178 history.push_or_extend_group(origin_id, kind, selections);
179 let mut edits = Vec::new();
180 for line_range in selections
181 .iter()
182 .copied()
183 .map(|selection| selection.line_range())
184 .merge(|line_range_0, line_range_1| {
185 if line_range_0.end >= line_range_1.start {
186 Ok(line_range_0.start..line_range_1.end)
187 } else {
188 Err((line_range_0, line_range_1))
189 }
190 })
191 {
192 for line_index in line_range {
193 f(
194 Editor {
195 history: &mut *history,
196 edits: &mut edits,
197 },
198 line_index,
199 );
200 }
201 }
202 drop(history);
203 self.update_after_edit(Some(origin_id), None, &edits);
204 }
205
206 pub fn add_decoration(&mut self, decoration: Decoration) {
207 self.0.decorations.borrow_mut().add_decoration(decoration);
208 }
209
210 pub fn clear_decorations(&mut self) {
211 self.0.decorations.borrow_mut().clear()
212 }
213
214 pub fn add_session(
215 &mut self,
216 session_id: SessionId,
217 edit_sender: Sender<(Option<SelectionSet>, Vec<Edit>)>,
218 ) {
219 self.0
220 .edit_senders
221 .borrow_mut()
222 .insert(session_id, edit_sender);
223 }
224
225 pub fn remove_session(&mut self, session_id: SessionId) {
226 self.0.edit_senders.borrow_mut().remove(&session_id);
227 }
228
229 fn autoindent(
230 &self,
231 line_ranges: &[Range<usize>],
232 indent_column_count: usize,
233 edits: &mut Vec<Edit>,
234 ) {
235 fn next_line_indent_column_count(line: &str, tab_column_count: usize) -> Option<usize> {
236 if let Some(indent) = line.indent() {
237 let mut indent_column_count = indent.column_count();
238 if line
239 .chars()
240 .rev()
241 .find_map(|char| {
242 if char.is_opening_delimiter() {
243 return Some(true);
244 }
245 if char.is_closing_delimiter() {
246 return Some(false);
247 }
248 None
249 })
250 .unwrap_or(false)
251 {
252 indent_column_count += tab_column_count;
253 };
254 Some(indent_column_count)
255 } else {
256 None
257 }
258 }
259
260 for line_range in line_ranges
261 .iter()
262 .cloned()
263 .merge(|line_range_0, line_range_1| {
264 if line_range_0.end >= line_range_1.start {
265 Ok(line_range_0.start..line_range_1.end)
266 } else {
267 Err((line_range_0, line_range_1))
268 }
269 })
270 {
271 let mut desired_indentation_column_count = self.as_text().as_lines()
272 [..line_range.start]
273 .iter()
274 .rev()
275 .find_map(|line| next_line_indent_column_count(line, indent_column_count))
276 .unwrap_or(0);
277 for line in line_range {
278 if self.as_text().as_lines()[line]
279 .chars()
280 .find_map(|char| {
281 if char.is_closing_delimiter() {
282 return Some(true);
283 }
284 if !char.is_whitespace() {
285 return Some(false);
286 }
287 None
288 })
289 .unwrap_or(false)
290 {
291 desired_indentation_column_count -= 4;
292 }
293 self.edit_lines_internal(line, edits, |line| {
294 crate::session::reindent(line, |_| desired_indentation_column_count)
295 });
296 if let Some(next_line_indentation_column_count) = next_line_indent_column_count(
297 &self.as_text().as_lines()[line],
298 indent_column_count,
299 ) {
300 desired_indentation_column_count = next_line_indentation_column_count;
301 }
302 }
303 }
304 }
305
306 fn edit_lines_internal(
307 &self,
308 line: usize,
309 edits: &mut Vec<Edit>,
310 mut f: impl FnMut(&str) -> (usize, usize, String),
311 ) {
312 let mut history = self.0.history.borrow_mut();
313 let (byte, delete_byte_count, insert_text) = f(&history.as_text().as_lines()[line]);
314 if delete_byte_count > 0 {
315 let edit = Edit {
316 change: Change::Delete(
317 Position {
318 line_index: line,
319 byte_index: byte,
320 },
321 Length {
322 line_count: 0,
323 byte_count: delete_byte_count,
324 },
325 ),
326 drift: Drift::Before,
327 };
328 edits.push(edit.clone());
329 history.apply_edit(edit);
330 }
331 if !insert_text.is_empty() {
332 let edit = Edit {
333 change: Change::Insert(
334 Position {
335 line_index: line,
336 byte_index: byte,
337 },
338 insert_text.into(),
339 ),
340 drift: Drift::Before,
341 };
342 edits.push(edit.clone());
343 history.apply_edit(edit);
344 }
345 }
346
347 pub fn force_new_group(&self) {
348 self.0.history.borrow_mut().force_new_group()
349 }
350
351 pub fn undo(&self, origin_id: SessionId, selections: &SelectionSet) -> bool {
352 let mut changes = Vec::new();
353 let selections = self.0.history.borrow_mut().undo(selections, &mut changes);
354 if let Some(selections) = selections {
355 self.update_after_edit(Some(origin_id), Some(selections), &changes);
356 true
357 } else {
358 false
359 }
360 }
361
362 pub fn redo(&self, origin_id: SessionId, selections: &SelectionSet) -> bool {
363 let mut changes = Vec::new();
364 let selections = self.0.history.borrow_mut().redo(selections, &mut changes);
365 if let Some(selections) = selections {
366 self.update_after_edit(Some(origin_id), Some(selections), &changes);
367 true
368 } else {
369 false
370 }
371 }
372
373 fn update_after_edit(
374 &self,
375 origin_id: Option<SessionId>,
376 selections: Option<SelectionSet>,
377 edits: &[Edit],
378 ) {
379 let mut layout = self.0.layout.borrow_mut();
380 for edit in edits {
381 match edit.change {
382 Change::Insert(position, ref text) => {
383 layout.indent_state[position.line_index] = None;
384 let line_count = text.length().line_count;
385 if line_count > 0 {
386 let line_index = position.line_index + 1;
387 layout
388 .indent_state
389 .splice(line_index..line_index, (0..line_count).map(|_| None));
390 }
391 }
392 Change::Delete(start, length) => {
393 layout.indent_state[start.line_index] = None;
394 if length.line_count > 0 {
395 let line_start = start.line_index + 1;
396 let line_end = line_start + length.line_count;
397 layout.indent_state.drain(line_start..line_end);
398 }
399 }
400 }
401 }
402 drop(layout);
403 for edit in edits {
404 self.apply_change_to_tokens(&edit.change);
405 self.apply_change_to_inline_inlays(&edit.change, edit.drift);
406 self.0.tokenizer.borrow_mut().apply_change(&edit.change);
407 }
408 self.update_indent_state();
409 self.0.tokenizer.borrow_mut().update(
410 self.0.history.borrow().as_text(),
411 &mut self.0.layout.borrow_mut().tokens,
412 );
413 let mut decorations = self.0.decorations.borrow_mut();
414 for edit in edits {
415 decorations.apply_edit(edit);
416 }
417 drop(decorations);
418 for (&session_id, edit_sender) in &*self.0.edit_senders.borrow() {
419 if Some(session_id) == origin_id {
420 edit_sender
421 .send((selections.clone(), edits.to_vec()))
422 .unwrap();
423 } else {
424 edit_sender
425 .send((
426 None,
427 edits
428 .iter()
429 .cloned()
430 .map(|edit| Edit {
431 change: edit.change,
432 drift: Drift::Before,
433 })
434 .collect(),
435 ))
436 .unwrap();
437 }
438 }
439 }
440
441 fn apply_change_to_tokens(&self, change: &Change) {
442 let mut layout = self.0.layout.borrow_mut();
443 let tokens = &mut layout.tokens;
444 match *change {
445 Change::Insert(point, ref text) => {
446 let mut byte = 0;
447 let mut index = tokens[point.line_index]
448 .iter()
449 .position(|token| {
450 if byte + token.len > point.byte_index {
451 return true;
452 }
453 byte += token.len;
454 false
455 })
456 .unwrap_or(tokens[point.line_index].len());
457 if byte != point.byte_index {
458 let token = tokens[point.line_index][index];
459 let mid = point.byte_index - byte;
460 tokens[point.line_index][index] = Token {
461 len: mid,
462 kind: token.kind,
463 };
464 index += 1;
465 tokens[point.line_index].insert(
466 index,
467 Token {
468 len: token.len - mid,
469 kind: token.kind,
470 },
471 );
472 }
473 if text.length().line_count == 0 {
474 tokens[point.line_index]
475 .splice(index..index, tokenize(text.as_lines().first().unwrap()));
476 } else {
477 let mut new_tokens = (0..text.as_lines().len())
478 .map(|line| tokenize(&text.as_lines()[line]).collect::<Vec<_>>())
479 .collect::<Vec<_>>();
480 new_tokens
481 .first_mut()
482 .unwrap()
483 .splice(..0, tokens[point.line_index][..index].iter().copied());
484 new_tokens
485 .last_mut()
486 .unwrap()
487 .splice(..0, tokens[point.line_index][index..].iter().copied());
488 tokens.splice(point.line_index..point.line_index + 1, new_tokens);
489 }
490 }
491 Change::Delete(start, length) => {
492 let end = start + length;
493 let mut byte = 0;
494 let mut start_token = tokens[start.line_index]
495 .iter()
496 .position(|token| {
497 if byte + token.len > start.byte_index {
498 return true;
499 }
500 byte += token.len;
501 false
502 })
503 .unwrap_or(tokens[start.line_index].len());
504 if byte != start.byte_index {
505 let token = tokens[start.line_index][start_token];
506 let mid = start.byte_index - byte;
507 tokens[start.line_index][start_token] = Token {
508 len: mid,
509 kind: token.kind,
510 };
511 start_token += 1;
512 tokens[start.line_index].insert(
513 start_token,
514 Token {
515 len: token.len - mid,
516 kind: token.kind,
517 },
518 );
519 }
520 let mut byte = 0;
521 let mut end_token = tokens[end.line_index]
522 .iter()
523 .position(|token| {
524 if byte + token.len > end.byte_index {
525 return true;
526 }
527 byte += token.len;
528 false
529 })
530 .unwrap_or(tokens[end.line_index].len());
531 if byte != end.byte_index {
532 let token = tokens[end.line_index][end_token];
533 let mid = end.byte_index - byte;
534 tokens[end.line_index][end_token] = Token {
535 len: mid,
536 kind: token.kind,
537 };
538 end_token += 1;
539 tokens[end.line_index].insert(
540 end_token,
541 Token {
542 len: token.len - mid,
543 kind: token.kind,
544 },
545 );
546 }
547 if length.line_count == 0 {
548 tokens[start.line_index].drain(start_token..end_token);
549 } else {
550 let mut new_tokens = tokens[start.line_index][..start_token]
551 .iter()
552 .copied()
553 .collect::<Vec<_>>();
554 new_tokens.extend(tokens[end.line_index][end_token..].iter().copied());
555 tokens.splice(start.line_index..end.line_index + 1, iter::once(new_tokens));
556 }
557 }
558 }
559 }
560
561 fn apply_change_to_inline_inlays(&self, change: &Change, drift: Drift) {
562 let mut layout = self.0.layout.borrow_mut();
563 let inline_inlays = &mut layout.inline_inlays;
564 match *change {
565 Change::Insert(point, ref text) => {
566 let index = inline_inlays[point.line_index]
567 .iter()
568 .position(|(byte, _)| match byte.cmp(&point.byte_index) {
569 Ordering::Less => false,
570 Ordering::Equal => match drift {
571 Drift::Before => true,
572 Drift::After => false,
573 },
574 Ordering::Greater => true,
575 })
576 .unwrap_or(inline_inlays[point.line_index].len());
577 if text.length().line_count == 0 {
578 for (byte, _) in &mut inline_inlays[point.line_index][index..] {
579 *byte += text.length().byte_count;
580 }
581 } else {
582 let mut new_inline_inlays = (0..text.as_lines().len())
583 .map(|_| Vec::new())
584 .collect::<Vec<_>>();
585 new_inline_inlays
586 .first_mut()
587 .unwrap()
588 .splice(..0, inline_inlays[point.line_index].drain(..index));
589 new_inline_inlays.last_mut().unwrap().splice(
590 ..0,
591 inline_inlays[point.line_index]
592 .drain(..)
593 .map(|(byte, inline_inlay)| {
594 (byte + text.length().byte_count, inline_inlay)
595 }),
596 );
597 inline_inlays.splice(point.line_index..point.line_index + 1, new_inline_inlays);
598 }
599 }
600 Change::Delete(start, length) => {
601 let end = start + length;
602 let start_inlay = inline_inlays[start.line_index]
603 .iter()
604 .position(|&(byte, _)| byte >= start.byte_index)
605 .unwrap_or(inline_inlays[start.line_index].len());
606 let end_inlay = inline_inlays[end.line_index]
607 .iter()
608 .position(|&(byte, _)| byte >= end.byte_index)
609 .unwrap_or(inline_inlays[end.line_index].len());
610 if length.line_count == 0 {
611 inline_inlays[start.line_index].drain(start_inlay..end_inlay);
612 for (byte, _) in &mut inline_inlays[start.line_index][start_inlay..] {
613 *byte = start.byte_index + (*byte - end.byte_index.min(*byte));
614 }
615 } else {
616 let mut new_inline_inlays = inline_inlays[start.line_index]
617 .drain(..start_inlay)
618 .collect::<Vec<_>>();
619 new_inline_inlays.extend(inline_inlays[end.line_index].drain(end_inlay..).map(
620 |(byte, inline_inlay)| {
621 (
622 start.byte_index + byte - end.byte_index.min(byte),
623 inline_inlay,
624 )
625 },
626 ));
627 inline_inlays.splice(
628 start.line_index..end.line_index + 1,
629 iter::once(new_inline_inlays),
630 );
631 }
632 }
633 }
634 }
635
636 fn update_indent_state(&self) {
637 let mut layout = self.0.layout.borrow_mut();
638 let indent_state = &mut layout.indent_state;
639 let history = self.0.history.borrow();
640 let lines = history.as_text().as_lines();
641 let mut current_indent_column_count = 0;
642 for line_index in 0..lines.len() {
643 match indent_state[line_index] {
644 Some(IndentState::NonEmpty(_, next_indent_column_count)) => {
645 current_indent_column_count = next_indent_column_count;
646 }
647 _ => {
648 indent_state[line_index] = Some(match lines[line_index].indent() {
649 Some(indent) => {
650 let indent_column_count = indent.column_count();
651 let mut next_indent_column_count = indent_column_count;
652 if lines[line_index]
653 .chars()
654 .rev()
655 .find_map(|char| {
656 if char.is_opening_delimiter() {
657 return Some(true);
658 }
659 if char.is_closing_delimiter() {
660 return Some(false);
661 }
662 None
663 })
664 .unwrap_or(false)
665 {
666 next_indent_column_count += 4;
667 }
668 current_indent_column_count = next_indent_column_count;
669 IndentState::NonEmpty(indent_column_count, next_indent_column_count)
670 }
671 None => IndentState::Empty(current_indent_column_count),
672 })
673 }
674 }
675 }
676 }
677}
678
679#[derive(Debug)]
680pub struct DocumentLayout {
681 pub indent_state: Vec<Option<IndentState>>,
682 pub tokens: Vec<Vec<Token>>,
683 pub inline_inlays: Vec<Vec<(usize, InlineInlay)>>,
684 pub block_inlays: Vec<(usize, BlockInlay)>,
685}
686
687#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
688pub enum IndentState {
689 Empty(usize),
690 NonEmpty(usize, usize),
691}
692
693#[derive(Debug)]
694pub struct Editor<'a> {
695 history: &'a mut History,
696 edits: &'a mut Vec<Edit>,
697}
698
699impl<'a> Editor<'a> {
700 pub fn as_text(&mut self) -> &Text {
701 self.history.as_text()
702 }
703
704 pub fn apply_edit(&mut self, edit: Edit) {
705 self.history.apply_edit(edit.clone());
706 self.edits.push(edit);
707 }
708}
709
710#[derive(Debug)]
711struct DocumentInner {
712 history: RefCell<History>,
713 layout: RefCell<DocumentLayout>,
714 tokenizer: RefCell<Tokenizer>,
715 decorations: RefCell<DecorationSet>,
716 edit_senders: RefCell<HashMap<SessionId, Sender<(Option<SelectionSet>, Vec<Edit>)>>>,
717}
718
719fn tokenize(text: &str) -> impl Iterator<Item = Token> + '_ {
720 text.split_whitespace_boundaries().map(|string| Token {
721 len: string.len(),
722 kind: if string.chars().next().unwrap().is_whitespace() {
723 TokenKind::Whitespace
724 } else {
725 TokenKind::Unknown
726 },
727 })
728}