1use std::collections::BTreeMap;
5use std::sync::Arc;
6use std::sync::atomic::{AtomicU64, Ordering};
7use std::time::{Duration, Instant};
8
9use crate::action::{Action, ActionError};
10use crate::buffer::{Buffer, BufferId, FileMeta, LineEdit};
11use crate::changeset::{Bias, ChangeSet};
12use crate::display::DisplayMap;
13use crate::fold::{self, FoldSet};
14use crate::history::Transaction;
15use crate::position::{ByteOffset, byte_to_line_col, line_col_to_byte};
16use crate::resolve::{Resolved, resolve, resolve_search};
17use crate::selection::{Selection, SelectionSet};
18use crate::view::{View, ViewId};
19
20pub trait Clock: Send {
22 fn now(&self) -> Duration;
23}
24
25pub struct SystemClock {
26 origin: Instant,
27}
28
29impl Default for SystemClock {
30 fn default() -> Self {
31 Self {
32 origin: Instant::now(),
33 }
34 }
35}
36
37impl Clock for SystemClock {
38 fn now(&self) -> Duration {
39 self.origin.elapsed()
40 }
41}
42
43#[derive(Clone, Default)]
45pub struct ManualClock(Arc<AtomicU64>);
46
47impl ManualClock {
48 pub fn advance(&self, d: Duration) {
49 self.0.fetch_add(d.as_millis() as u64, Ordering::Relaxed);
50 }
51}
52
53impl Clock for ManualClock {
54 fn now(&self) -> Duration {
55 Duration::from_millis(self.0.load(Ordering::Relaxed))
56 }
57}
58
59#[derive(Clone, Debug)]
60pub struct Settings {
61 pub tab_width: usize,
62 pub use_spaces: bool,
64}
65
66impl Default for Settings {
67 fn default() -> Self {
68 Self {
69 tab_width: 4,
70 use_spaces: false,
71 }
72 }
73}
74
75pub struct Editor {
76 buffers: BTreeMap<BufferId, Buffer>,
77 views: BTreeMap<ViewId, View>,
78 next_id: u64,
79 pub settings: Settings,
80 clock: Box<dyn Clock>,
81 recording: Option<Vec<Action>>,
82}
83
84impl Default for Editor {
85 fn default() -> Self {
86 Self::with_clock(Box::new(SystemClock::default()))
87 }
88}
89
90impl Editor {
91 pub fn new() -> Self {
92 Self::default()
93 }
94
95 pub fn with_clock(clock: Box<dyn Clock>) -> Self {
96 Self {
97 buffers: BTreeMap::new(),
98 views: BTreeMap::new(),
99 next_id: 1,
100 settings: Settings::default(),
101 clock,
102 recording: None,
103 }
104 }
105
106 fn fresh_id(&mut self) -> u64 {
107 let id = self.next_id;
108 self.next_id += 1;
109 id
110 }
111
112 pub fn add_buffer(&mut self, text: &str, meta: FileMeta) -> BufferId {
113 let id = BufferId(self.fresh_id());
114 self.buffers.insert(id, Buffer::new(id, text, meta));
115 id
116 }
117
118 pub fn add_view(&mut self, buffer: BufferId) -> Result<ViewId, ActionError> {
119 if !self.buffers.contains_key(&buffer) {
120 return Err(ActionError::UnknownBuffer(buffer));
121 }
122 let id = ViewId(self.fresh_id());
123 self.views.insert(id, View::new(id, buffer));
124 Ok(id)
125 }
126
127 pub fn remove_view(&mut self, view: ViewId) -> Option<View> {
128 self.views.remove(&view)
129 }
130
131 pub fn remove_buffer(&mut self, buffer: BufferId) -> Option<Buffer> {
133 self.views.retain(|_, v| v.buffer() != buffer);
134 self.buffers.remove(&buffer)
135 }
136
137 pub fn buffer(&self, id: BufferId) -> Option<&Buffer> {
138 self.buffers.get(&id)
139 }
140
141 pub fn buffer_mut(&mut self, id: BufferId) -> Option<&mut Buffer> {
142 self.buffers.get_mut(&id)
143 }
144
145 pub fn view(&self, id: ViewId) -> Option<&View> {
146 self.views.get(&id)
147 }
148
149 pub fn view_mut(&mut self, id: ViewId) -> Option<&mut View> {
150 self.views.get_mut(&id)
151 }
152
153 pub fn buffers(&self) -> impl Iterator<Item = &Buffer> {
154 self.buffers.values()
155 }
156
157 pub fn buffers_mut(&mut self) -> impl Iterator<Item = &mut Buffer> {
158 self.buffers.values_mut()
159 }
160
161 pub fn views(&self) -> impl Iterator<Item = &View> {
162 self.views.values()
163 }
164
165 pub fn views_of(&self, buffer: BufferId) -> impl Iterator<Item = &View> {
167 self.views
168 .values()
169 .filter(move |v| v.buffer() == buffer && !v.is_aux())
170 }
171
172 pub fn add_aux_view(&mut self, buffer: BufferId) -> Result<ViewId, ActionError> {
176 let id = self.add_view(buffer)?;
177 if let Some(v) = self.views.get_mut(&id) {
178 v.set_aux();
179 }
180 Ok(id)
181 }
182
183 pub fn start_recording(&mut self) {
184 self.recording = Some(Vec::new());
185 }
186
187 pub fn is_recording(&self) -> bool {
188 self.recording.is_some()
189 }
190
191 pub fn stop_recording(&mut self) -> Vec<Action> {
192 self.recording.take().unwrap_or_default()
193 }
194
195 pub fn recorded(&self) -> Option<&[Action]> {
197 self.recording.as_deref()
198 }
199
200 pub(crate) fn take_recording(&mut self) -> Option<Vec<Action>> {
201 self.recording.take()
202 }
203
204 pub(crate) fn restore_recording(&mut self, recording: Option<Vec<Action>>) {
205 self.recording = recording;
206 }
207
208 pub fn begin_undo_group(&mut self, view: ViewId) -> Result<(), ActionError> {
211 let (buffer, _) = self.lookup(view)?;
212 self.buffers
213 .get_mut(&buffer)
214 .ok_or(ActionError::UnknownBuffer(buffer))?
215 .history
216 .begin_group();
217 Ok(())
218 }
219
220 pub fn end_undo_group(&mut self, view: ViewId) -> Result<(), ActionError> {
221 let (buffer, _) = self.lookup(view)?;
222 self.buffers
223 .get_mut(&buffer)
224 .ok_or(ActionError::UnknownBuffer(buffer))?
225 .history
226 .end_group();
227 Ok(())
228 }
229
230 fn lookup(&self, view: ViewId) -> Result<(BufferId, &View), ActionError> {
231 let v = self
232 .views
233 .get(&view)
234 .ok_or(ActionError::UnknownView(view))?;
235 if !self.buffers.contains_key(&v.buffer()) {
236 return Err(ActionError::UnknownBuffer(v.buffer()));
237 }
238 Ok((v.buffer(), v))
239 }
240
241 pub fn apply(&mut self, view: ViewId, action: Action) -> Result<(), ActionError> {
245 let (buffer_id, _) = self.lookup(view)?;
246 let read_only = self.buffers.get(&buffer_id).is_some_and(|b| b.read_only);
247 match &action {
248 Action::Undo | Action::Redo if read_only => return Err(ActionError::ReadOnly),
249 Action::Undo => self.undo(view, buffer_id),
250 Action::Redo => self.redo(view, buffer_id),
251 Action::Fold
252 | Action::Unfold
253 | Action::ToggleFold
254 | Action::FoldAll
255 | Action::UnfoldAll
256 | Action::FoldLevel(_)
257 | Action::UnfoldLevel(_) => self.fold_action(view, buffer_id, &action),
258 _ => {
259 let resolved = self.resolve_in(view, buffer_id, &action)??;
260 self.commit(view, buffer_id, resolved)?;
261 }
262 }
263 self.sync_folds(buffer_id);
264 if let Some(rec) = &mut self.recording
265 && action.is_recordable()
266 {
267 rec.push(action);
268 }
269 Ok(())
270 }
271
272 pub fn apply_unrecorded(&mut self, view: ViewId, action: Action) -> Result<(), ActionError> {
276 let recording = self.recording.take();
277 let result = self.apply(view, action);
278 self.recording = recording;
279 result
280 }
281
282 fn resolve_in(
285 &self,
286 view: ViewId,
287 buffer_id: BufferId,
288 action: &Action,
289 ) -> Result<Result<Resolved, ActionError>, ActionError> {
290 let buffer = self
291 .buffers
292 .get(&buffer_id)
293 .ok_or(ActionError::UnknownBuffer(buffer_id))?;
294 let v = self
295 .views
296 .get(&view)
297 .ok_or(ActionError::UnknownView(view))?;
298 let sels = &v.selections;
299 Ok(match action {
300 Action::Find { .. }
301 | Action::Replace { .. }
302 | Action::ReplaceAll { .. }
303 | Action::SelectAllMatches(_) => resolve_search(action, &buffer.doc, sels),
304 _ => {
305 let rows = DisplayMap::new(buffer, v, self.settings.tab_width);
306 Ok(resolve(action, &buffer.doc, sels, &self.settings, &rows))
307 }
308 })
309 }
310
311 fn commit(
314 &mut self,
315 view: ViewId,
316 buffer_id: BufferId,
317 resolved: Resolved,
318 ) -> Result<(), ActionError> {
319 match resolved {
320 Resolved::Selections(sels) => {
321 if let Some(b) = self.buffers.get_mut(&buffer_id) {
322 b.history.break_coalescing();
323 }
324 self.set_selections(view, sels);
325 }
326 Resolved::Edit { .. } if self.buffers.get(&buffer_id).is_some_and(|b| b.read_only) => {
327 return Err(ActionError::ReadOnly);
328 }
329 Resolved::Edit {
330 changes,
331 after,
332 kind,
333 } => {
334 let now = self.clock.now();
335 let before = self.views[&view].selections.clone();
336 let Some(buffer) = self.buffers.get_mut(&buffer_id) else {
337 return Err(ActionError::UnknownBuffer(buffer_id));
338 };
339 let inverse = changes.invert(&buffer.doc);
340 apply_changes(buffer, &changes);
341 let rev_before = buffer.revision;
342 let rev_after = buffer.next_revision;
343 buffer.next_revision += 1;
344 buffer.revision = rev_after;
345 buffer.history.push(
346 Transaction {
347 changes: changes.clone(),
348 inverse,
349 before,
350 after: after.clone(),
351 },
352 kind,
353 rev_before,
354 rev_after,
355 now,
356 );
357 self.set_selections(view, after);
358 self.map_other_views(buffer_id, view, &changes);
359 self.map_folds(buffer_id, &changes);
360 }
361 }
362 Ok(())
363 }
364
365 pub fn reload_buffer(
369 &mut self,
370 buffer: BufferId,
371 text: &str,
372 meta: FileMeta,
373 ) -> Result<(), ActionError> {
374 let view = self
375 .views_of(buffer)
376 .next()
377 .map(View::id)
378 .ok_or(ActionError::UnknownBuffer(buffer))?;
379 let b = self
380 .buffers
381 .get(&buffer)
382 .ok_or(ActionError::UnknownBuffer(buffer))?;
383 if b.doc.to_string() != text {
384 let new_doc = crate::text::Document::new(text);
385 let remap = |p: ByteOffset| {
386 let lc = byte_to_line_col(&b.doc, p);
387 let mut q = line_col_to_byte(&new_doc, lc);
388 while !new_doc.is_char_boundary(q) {
389 q.0 -= 1;
390 }
391 q
392 };
393 let after = self.views[&view]
394 .selections
395 .map(|s| Selection::new(remap(s.anchor), remap(s.head)));
396 let changes = ChangeSet::new(
397 b.doc.len(),
398 vec![crate::changeset::Edit::new(
399 ByteOffset(0),
400 b.doc.len(),
401 text,
402 )],
403 );
404 self.commit(
405 view,
406 buffer,
407 Resolved::Edit {
408 changes,
409 after,
410 kind: crate::history::EditKind::Other,
411 },
412 )?;
413 }
414 if let Some(b) = self.buffers.get_mut(&buffer) {
415 b.meta = meta;
416 b.mark_saved();
417 }
418 self.sync_folds(buffer);
419 Ok(())
420 }
421
422 fn undo(&mut self, view: ViewId, buffer_id: BufferId) {
423 let Some(buffer) = self.buffers.get_mut(&buffer_id) else {
424 return;
425 };
426 let Some(step) = buffer.history.pop_undo() else {
427 return;
428 };
429 let inverses: Vec<ChangeSet> = step.txns.iter().rev().map(|t| t.inverse.clone()).collect();
430 for inv in &inverses {
431 apply_changes(buffer, inv);
432 }
433 buffer.revision = step.rev_before;
434 let sels = step.txns[0].before.clone();
435 buffer.history.push_redo(step);
436 self.set_selections(view, sels);
437 for inv in &inverses {
438 self.map_other_views(buffer_id, view, inv);
439 self.map_folds(buffer_id, inv);
440 }
441 }
442
443 fn redo(&mut self, view: ViewId, buffer_id: BufferId) {
444 let Some(buffer) = self.buffers.get_mut(&buffer_id) else {
445 return;
446 };
447 let Some(step) = buffer.history.pop_redo() else {
448 return;
449 };
450 let changes: Vec<ChangeSet> = step.txns.iter().map(|t| t.changes.clone()).collect();
451 for cs in &changes {
452 apply_changes(buffer, cs);
453 }
454 buffer.revision = step.rev_after;
455 let sels = step.txns[step.txns.len() - 1].after.clone();
456 buffer.history.push_undo(step);
457 self.set_selections(view, sels);
458 for cs in &changes {
459 self.map_other_views(buffer_id, view, cs);
460 self.map_folds(buffer_id, cs);
461 }
462 }
463
464 fn set_selections(&mut self, view: ViewId, sels: SelectionSet) {
465 if let Some(v) = self.views.get_mut(&view) {
466 v.selections = sels;
467 }
468 }
469
470 fn map_folds(&mut self, buffer: BufferId, changes: &ChangeSet) {
474 for v in self.views.values_mut() {
475 if v.buffer() == buffer && !v.folds.is_empty() {
476 v.folds.map(changes);
477 }
478 }
479 }
480
481 fn sync_folds(&mut self, buffer: BufferId) {
484 let Some(doc) = self.buffers.get(&buffer).map(|b| &b.doc) else {
485 return;
486 };
487 for v in self.views.values_mut() {
488 if v.buffer() != buffer {
489 continue;
490 }
491 v.folds.relines(doc);
494 if v.folds.is_empty() {
495 continue;
496 }
497 let hidden: Vec<usize> = v
498 .selections
499 .ranges()
500 .iter()
501 .map(|s| doc.line_of(s.head))
502 .filter(|&l| v.folds.is_hidden(l))
503 .collect();
504 if !hidden.is_empty() {
505 v.folds
506 .retain(|header, last| !hidden.iter().any(|&l| header < l && l <= last));
507 }
508 }
509 }
510
511 pub fn fold_at(&mut self, view: ViewId, line: usize) -> bool {
514 let tab_width = self.settings.tab_width;
515 let Some(v) = self.views.get_mut(&view) else {
516 return false;
517 };
518 let Some(b) = self.buffers.get(&v.buffer()) else {
519 return false;
520 };
521 let Some(last) = fold::region(&b.doc, line, b.fold_strategy, tab_width) else {
522 return false;
523 };
524 v.folds.insert(&b.doc, [(line, last)]);
525 reveal_carets(&b.doc, v);
526 true
527 }
528
529 pub fn unfold_at(&mut self, view: ViewId, line: usize) -> bool {
531 self.views
532 .get_mut(&view)
533 .is_some_and(|v| v.folds.remove(line))
534 }
535
536 pub fn toggle_fold_at(&mut self, view: ViewId, line: usize) -> bool {
538 self.unfold_at(view, line) || self.fold_at(view, line)
539 }
540
541 fn fold_action(&mut self, view: ViewId, buffer: BufferId, action: &Action) {
542 let tab_width = self.settings.tab_width;
543 let (Some(v), Some(b)) = (self.views.get_mut(&view), self.buffers.get(&buffer)) else {
544 return;
545 };
546 let (doc, strategy) = (&b.doc, b.fold_strategy);
547 let caret = doc.line_of(v.selections.primary().head);
548 let around = || fold::enclosing(doc, caret, strategy, tab_width);
549 match action {
550 Action::Fold => {
551 if let Some(r) = around() {
552 v.folds.insert(doc, [r]);
553 }
554 }
555 Action::ToggleFold => {
556 if !v.folds.remove(caret)
557 && let Some(r) = around()
558 {
559 v.folds.insert(doc, [r]);
560 }
561 }
562 Action::Unfold => {
563 if !v.folds.remove(caret)
564 && let Some((header, last)) = around()
565 {
566 v.folds.retain(|h, _| h < header || h > last);
567 }
568 }
569 Action::FoldAll => {
570 let all = fold::regions(doc, strategy, tab_width);
571 v.folds.insert(doc, all.iter().map(|r| (r.header, r.last)));
572 }
573 Action::UnfoldAll => v.folds = FoldSet::default(),
574 Action::FoldLevel(n) => {
575 let all = fold::regions(doc, strategy, tab_width);
576 let level = all.iter().filter(|r| r.level == *n);
577 v.folds.insert(doc, level.map(|r| (r.header, r.last)));
578 }
579 Action::UnfoldLevel(n) => {
580 let level: std::collections::HashSet<usize> =
581 fold::regions(doc, strategy, tab_width)
582 .into_iter()
583 .filter(|r| r.level == *n)
584 .map(|r| r.header)
585 .collect();
586 v.folds.retain(|h, _| !level.contains(&h));
587 }
588 _ => {}
589 }
590 reveal_carets(doc, v);
591 }
592
593 fn map_other_views(&mut self, buffer: BufferId, except: ViewId, changes: &ChangeSet) {
596 for v in self.views.values_mut() {
597 if v.buffer() == buffer && v.id() != except {
598 v.selections = v.selections.map(|s| Selection {
599 anchor: changes.map_position(s.anchor, Bias::Before),
600 head: changes.map_position(s.head, Bias::Before),
601 goal: s.goal,
602 });
603 }
604 }
605 }
606}
607
608fn reveal_carets(doc: &crate::text::Document, v: &mut View) {
611 let folds = &v.folds;
612 if folds.is_empty() {
613 return;
614 }
615 let moved = v.selections.map(|s| {
616 let Some((start, _)) = folds.hidden_range(doc.line_of(s.head)) else {
617 return s.clone();
618 };
619 let head = doc.line_end(start - 1);
620 if s.is_empty() {
621 Selection::caret(head)
622 } else {
623 Selection::new(s.anchor, head)
624 }
625 });
626 v.selections = moved;
627}
628
629fn apply_changes(buffer: &mut Buffer, changes: &ChangeSet) {
630 for e in changes.edits().iter().rev() {
633 let start = buffer.doc.line_of(e.start);
634 let edit = LineEdit {
635 start,
636 old_end: buffer.doc.line_of(e.end),
637 new_end: start + e.text.bytes().filter(|&b| b == b'\n').count(),
638 };
639 buffer.record_line_edit(edit);
640 }
641 changes.apply(&mut buffer.doc);
642}