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