@@ -15,7 +15,7 @@ use crate::ui::{self, Prompt, PromptEvent};
1515use helix_view::{
1616 document::Mode,
1717 view::{View, PADDING},
18− Editor,
18+ Document, Editor,
1919};
2020
2121pub struct Context<'a> {
@@ -27,9 +27,15 @@ pub struct Context<'a> {
2727}
2828
2929impl<'a> Context<'a> {
30+ #[inline]
3031 pub fn view(&mut self) -> &mut View {
3132 self.editor.view_mut()
3233 }
34+
35+ #[inline]
36+ pub fn doc(&mut self) -> &mut Document {
37+ &mut self.editor.view_mut().doc
38+ }
3339}
3440
3541/// A command is a function that takes the current state and a count, and does a side-effect on the
@@ -39,45 +45,41 @@ pub type Command = fn(cx: &mut Context);
3945pub fn move_char_left(cx: &mut Context) {
4046 let count = cx.count;
4147 let selection =
42− cx.view()
43− .doc
48+ cx.doc()
4449 .state
4550 .move_selection(Direction::Backward, Granularity::Character, count);
46− cx.view().doc.set_selection(selection);
51+ cx.doc().set_selection(selection);
4752}
4853
4954pub fn move_char_right(cx: &mut Context) {
5055 let count = cx.count;
5156 let selection =
52− cx.view()
53− .doc
57+ cx.doc()
5458 .state
5559 .move_selection(Direction::Forward, Granularity::Character, count);
56− cx.view().doc.set_selection(selection);
60+ cx.doc().set_selection(selection);
5761}
5862
5963pub fn move_line_up(cx: &mut Context) {
6064 let count = cx.count;
61− let selection =
62− cx.view()
63− .doc
64− .state
65− .move_selection(Direction::Backward, Granularity::Line, count);
66− cx.view().doc.set_selection(selection);
65+ let selection = cx
66+ .doc()
67+ .state
68+ .move_selection(Direction::Backward, Granularity::Line, count);
69+ cx.doc().set_selection(selection);
6770}
6871
6972pub fn move_line_down(cx: &mut Context) {
7073 let count = cx.count;
71− let selection =
72− cx.view()
73− .doc
74− .state
75− .move_selection(Direction::Forward, Granularity::Line, count);
76− cx.view().doc.set_selection(selection);
74+ let selection = cx
75+ .doc()
76+ .state
77+ .move_selection(Direction::Forward, Granularity::Line, count);
78+ cx.doc().set_selection(selection);
7779}
7880
7981pub fn move_line_end(cx: &mut Context) {
80− let lines = selection_lines(&cx.view().doc.state);
82+ let lines = selection_lines(&cx.doc().state);
8183
8284 let positions = lines
8385 .into_iter()
@@ -86,90 +88,83 @@ pub fn move_line_end(cx: &mut Context) {
8688
8789 // Line end is pos at the start of next line - 1
8890 // subtract another 1 because the line ends with \n
89− cx.view()
90− .doc
91− .text()
92− .line_to_char(index + 1)
93− .saturating_sub(2)
91+ cx.doc().text().line_to_char(index + 1).saturating_sub(2)
9492 })
9593 .map(|pos| Range::new(pos, pos));
9694
9795 let selection = Selection::new(positions.collect(), 0);
9896
99− cx.view().doc.set_selection(selection);
97+ cx.doc().set_selection(selection);
10098}
10199
102100pub fn move_line_start(cx: &mut Context) {
103− let lines = selection_lines(&cx.view().doc.state);
101+ let lines = selection_lines(&cx.doc().state);
104102
105103 let positions = lines
106104 .into_iter()
107105 .map(|index| {
108106 // adjust all positions to the start of the line.
109− cx.view().doc.text().line_to_char(index)
107+ cx.doc().text().line_to_char(index)
110108 })
111109 .map(|pos| Range::new(pos, pos));
112110
113111 let selection = Selection::new(positions.collect(), 0);
114112
115− cx.view().doc.set_selection(selection);
113+ cx.doc().set_selection(selection);
116114}
117115
118116pub fn move_next_word_start(cx: &mut Context) {
119117 let count = cx.count;
120− let view = cx.view();
121− let pos = view.doc.state.move_pos(
122− view.doc.selection().cursor(),
118+ let doc = cx.doc();
119+ let pos = doc.state.move_pos(
120+ doc.selection().cursor(),
123121 Direction::Forward,
124122 Granularity::Word,
125123 count,
126124 );
127125
128− view.doc.set_selection(Selection::point(pos));
126+ doc.set_selection(Selection::point(pos));
129127}
130128
131129pub fn move_prev_word_start(cx: &mut Context) {
132130 let count = cx.count;
133− let view = cx.view();
134− let pos = view.doc.state.move_pos(
135− view.doc.selection().cursor(),
131+ let doc = cx.doc();
132+ let pos = doc.state.move_pos(
133+ doc.selection().cursor(),
136134 Direction::Backward,
137135 Granularity::Word,
138136 count,
139137 );
140138
141− view.doc.set_selection(Selection::point(pos));
139+ doc.set_selection(Selection::point(pos));
142140}
143141
144142pub fn move_next_word_end(cx: &mut Context) {
145143 let count = cx.count;
146− let view = cx.view();
147− let pos = State::move_next_word_end(
148− &view.doc.text().slice(..),
149− view.doc.selection().cursor(),
150− count,
151− );
144+ let doc = cx.doc();
145+ let pos = State::move_next_word_end(&doc.text().slice(..), doc.selection().cursor(), count);
152146
153− view.doc.set_selection(Selection::point(pos));
147+ doc.set_selection(Selection::point(pos));
154148}
155149
156150pub fn move_file_start(cx: &mut Context) {
157− cx.view().doc.set_selection(Selection::point(0));
151+ cx.doc().set_selection(Selection::point(0));
158152
159− cx.view().doc.mode = Mode::Normal;
153+ cx.doc().mode = Mode::Normal;
160154}
161155
162156pub fn move_file_end(cx: &mut Context) {
163− let text = &cx.view().doc.text();
157+ let text = &cx.doc().text();
164158 let last_line = text.line_to_char(text.len_lines().saturating_sub(2));
165− cx.view().doc.set_selection(Selection::point(last_line));
159+ cx.doc().set_selection(Selection::point(last_line));
166160
167− cx.view().doc.mode = Mode::Normal;
161+ cx.doc().mode = Mode::Normal;
168162}
169163
170164pub fn check_cursor_in_view(view: &View) -> bool {
171− let cursor = view.doc.selection().cursor();
172− let line = view.doc.text().char_to_line(cursor);
165+ let doc = &view.doc;
166+ let cursor = doc.selection().cursor();
167+ let line = doc.text().char_to_line(cursor);
173168 let document_end = view.first_line + view.size.1.saturating_sub(1) as usize;
174169
175170 if (line > document_end.saturating_sub(PADDING)) | (line < view.first_line + PADDING) {
@@ -235,42 +230,38 @@ pub fn half_page_down(cx: &mut Context) {
235230
236231pub fn extend_char_left(cx: &mut Context) {
237232 let count = cx.count;
238− let view = cx.view();
239− let selection =
240− view.doc
241− .state
242− .extend_selection(Direction::Backward, Granularity::Character, count);
243− view.doc.set_selection(selection);
233+ let doc = cx.doc();
234+ let selection = doc
235+ .state
236+ .extend_selection(Direction::Backward, Granularity::Character, count);
237+ doc.set_selection(selection);
244238}
245239
246240pub fn extend_char_right(cx: &mut Context) {
247241 let count = cx.count;
248− let view = cx.view();
249− let selection =
250− view.doc
251− .state
252− .extend_selection(Direction::Forward, Granularity::Character, count);
253− view.doc.set_selection(selection);
242+ let doc = cx.doc();
243+ let selection = doc
244+ .state
245+ .extend_selection(Direction::Forward, Granularity::Character, count);
246+ doc.set_selection(selection);
254247}
255248
256249pub fn extend_line_up(cx: &mut Context) {
257250 let count = cx.count;
258− let view = cx.view();
259− let selection = view
260− .doc
251+ let doc = cx.doc();
252+ let selection = doc
261253 .state
262254 .extend_selection(Direction::Backward, Granularity::Line, count);
263− view.doc.set_selection(selection);
255+ doc.set_selection(selection);
264256}
265257
266258pub fn extend_line_down(cx: &mut Context) {
267259 let count = cx.count;
268− let view = cx.view();
269− let selection = view
270− .doc
260+ let doc = cx.doc();
261+ let selection = doc
271262 .state
272263 .extend_selection(Direction::Forward, Granularity::Line, count);
273− view.doc.set_selection(selection);
264+ doc.set_selection(selection);
274265}
275266
276267pub fn split_selection(cx: &mut Context) {
@@ -287,7 +278,7 @@ pub fn split_selection(cx: &mut Context) {
287278 // # update state
288279 // }
289280
290− let snapshot = cx.view().doc.state.clone();
281+ let snapshot = cx.doc().state.clone();
291282
292283 let prompt = Prompt::new(
293284 "split:".to_string(),
@@ -296,8 +287,8 @@ pub fn split_selection(cx: &mut Context) {
296287 match event {
297288 PromptEvent::Abort => {
298289 // revert state
299− let view = editor.view_mut();
300− view.doc.state = snapshot.clone();
290+ let doc = &mut editor.view_mut().doc;
291+ doc.state = snapshot.clone();
301292 }
302293 PromptEvent::Validate => {
303294 //
@@ -305,15 +296,15 @@ pub fn split_selection(cx: &mut Context) {
305296 PromptEvent::Update => {
306297 match Regex::new(input) {
307298 Ok(regex) => {
308− let view = editor.view_mut();
299+ let doc = &mut editor.view_mut().doc;
309300
310301 // revert state to what it was before the last update
311− view.doc.state = snapshot.clone();
302+ doc.state = snapshot.clone();
312303
313− let text = &view.doc.text().slice(..);
304+ let text = &doc.text().slice(..);
314305 let selection =
315− selection::split_on_matches(text, view.doc.selection(), ®ex);
316− view.doc.set_selection(selection);
306+ selection::split_on_matches(text, doc.selection(), ®ex);
307+ doc.set_selection(selection);
317308 }
318309 Err(_err) => (), // TODO: mark command line as error
319310 }
@@ -330,33 +321,33 @@ pub fn split_selection(cx: &mut Context) {
330321}
331322
332323pub fn split_selection_on_newline(cx: &mut Context) {
333− let view = cx.view();
334− let text = &view.doc.text().slice(..);
324+ let doc = cx.doc();
325+ let text = &doc.text().slice(..);
335326 // only compile the regex once
336327 #[allow(clippy::trivial_regex)]
337328 static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\n").unwrap());
338− let selection = selection::split_on_matches(text, view.doc.selection(), ®EX);
339− view.doc.set_selection(selection);
329+ let selection = selection::split_on_matches(text, doc.selection(), ®EX);
330+ doc.set_selection(selection);
340331}
341332
342333pub fn select_line(cx: &mut Context) {
343334 // TODO: count
344− let pos = cx.view().doc.selection().primary();
345− let text = cx.view().doc.text();
335+ let pos = cx.doc().selection().primary();
336+ let text = cx.doc().text();
346337 let line = text.char_to_line(pos.head);
347338 let start = text.line_to_char(line);
348339 let end = text.line_to_char(line + 1).saturating_sub(1);
349340
350− cx.view().doc.set_selection(Selection::single(start, end));
341+ cx.doc().set_selection(Selection::single(start, end));
351342}
352343
353344// heuristic: append changes to history after each command, unless we're in insert mode
354345
355346fn _delete_selection(cx: &mut Context) {
356− let transaction = Transaction::change_by_selection(&cx.view().doc.state, |range| {
347+ let transaction = Transaction::change_by_selection(&cx.doc().state, |range| {
357348 (range.from(), range.to() + 1, None)
358349 });
359− cx.view().doc.apply(&transaction);
350+ cx.doc().apply(&transaction);
360351}
361352
362353pub fn delete_selection(cx: &mut Context) {
@@ -377,7 +368,7 @@ pub fn collapse_selection(cx: &mut Context) {
377368 .selection()
378369 .transform(|range| Range::new(range.head, range.head));
379370
380− cx.view().doc.set_selection(selection);
371+ cx.doc().set_selection(selection);
381372}
382373
383374pub fn flip_selections(cx: &mut Context) {
@@ -387,11 +378,11 @@ pub fn flip_selections(cx: &mut Context) {
387378 .selection()
388379 .transform(|range| Range::new(range.head, range.anchor));
389380
390− cx.view().doc.set_selection(selection);
381+ cx.doc().set_selection(selection);
391382}
392383
393384fn enter_insert_mode(cx: &mut Context) {
394− cx.view().doc.mode = Mode::Insert;
385+ cx.doc().mode = Mode::Insert;
395386
396387 // TODO: store selection for undo
397388}
@@ -405,25 +396,25 @@ pub fn insert_mode(cx: &mut Context) {
405396 .doc
406397 .selection()
407398 .transform(|range| Range::new(range.to(), range.from()));
408− cx.view().doc.set_selection(selection);
399+ cx.doc().set_selection(selection);
409400}
410401
411402// inserts at the end of each selection
412403pub fn append_mode(cx: &mut Context) {
413404 enter_insert_mode(cx);
414− let view = cx.view();
415− view.doc.restore_cursor = true;
405+ let doc = cx.doc();
406+ doc.restore_cursor = true;
416407
417408 // TODO: as transaction
418− let text = &view.doc.text().slice(..);
419− let selection = view.doc.selection().transform(|range| {
409+ let text = &doc.text().slice(..);
410+ let selection = doc.selection().transform(|range| {
420411 // TODO: to() + next char
421412 Range::new(
422413 range.from(),
423414 graphemes::next_grapheme_boundary(text, range.to()),
424415 )
425416 });
426− view.doc.set_selection(selection);
417+ doc.set_selection(selection);
427418}
428419
429420// TODO: I, A, o and O can share a lot of the primitives.
@@ -545,23 +536,23 @@ pub fn append_to_line(cx: &mut Context) {
545536pub fn open_below(cx: &mut Context) {
546537 enter_insert_mode(cx);
547538
548− let view = cx.view();
539+ let doc = cx.doc();
549540
550− let lines = selection_lines(&view.doc.state);
541+ let lines = selection_lines(&doc.state);
551542
552543 let positions: Vec<_> = lines
553544 .into_iter()
554545 .map(|index| {
555546 // adjust all positions to the end of the line/start of the next one.
556− view.doc.text().line_to_char(index + 1)
547+ doc.text().line_to_char(index + 1)
557548 })
558549 .collect();
559550
560551 let changes = positions.iter().copied().map(|index| {
561552 // TODO: share logic with insert_newline for indentation
562553 let indent_level = helix_core::indent::suggested_indent_for_pos(
563− view.doc.syntax.as_ref(),
564− &view.doc.state,
554+ doc.syntax.as_ref(),
555+ &doc.state,
565556 index,
566557 true,
567558 );
@@ -595,29 +586,29 @@ pub fn open_below(cx: &mut Context) {
595586 0,
596587 );
597588
598− let transaction = Transaction::change(&view.doc.state, changes).with_selection(selection);
589+ let transaction = Transaction::change(&doc.state, changes).with_selection(selection);
599590
600− view.doc.apply(&transaction);
591+ doc.apply(&transaction);
601592}
602593
603594// O inserts a new line before each line with a selection
604595
605596fn append_changes_to_history(cx: &mut Context) {
606− if cx.view().doc.changes.is_empty() {
597+ if cx.doc().changes.is_empty() {
607598 return;
608599 }
609600
610601 // TODO: change -> change -> undo -> change -> change fails, probably old_state needs reset
611602
612− let new_changeset = ChangeSet::new(cx.view().doc.text());
613− let changes = std::mem::replace(&mut cx.view().doc.changes, new_changeset);
603+ let new_changeset = ChangeSet::new(cx.doc().text());
604+ let changes = std::mem::replace(&mut cx.doc().changes, new_changeset);
614605 // Instead of doing this messy merge we could always commit, and based on transaction
615606 // annotations either add a new layer or compose into the previous one.
616− let transaction = Transaction::from(changes).with_selection(cx.view().doc.selection().clone());
607+ let transaction = Transaction::from(changes).with_selection(cx.doc().selection().clone());
617608
618609 // increment document version
619610 // TODO: needs to happen on undo/redo too
620− cx.view().doc.version += 1;
611+ cx.doc().version += 1;
621612
622613 // TODO: trigger lsp/documentDidChange with changes
623614
@@ -630,38 +621,35 @@ fn append_changes_to_history(cx: &mut Context) {
630621 .expect("no old_state available");
631622
632623 // TODO: take transaction by value?
633− cx.view()
634− .doc
635− .history
636− .commit_revision(&transaction, &old_state);
624+ cx.doc().history.commit_revision(&transaction, &old_state);
637625
638626 // TODO: notify LSP of changes
639627}
640628
641629pub fn normal_mode(cx: &mut Context) {
642− cx.view().doc.mode = Mode::Normal;
630+ cx.doc().mode = Mode::Normal;
643631
644632 append_changes_to_history(cx);
645633
646− let view = cx.view();
634+ let doc = cx.doc();
647635
648636 // if leaving append mode, move cursor back by 1
649− if view.doc.restore_cursor {
650− let text = &view.doc.text().slice(..);
651− let selection = view.doc.selection().transform(|range| {
637+ if doc.restore_cursor {
638+ let text = &doc.text().slice(..);
639+ let selection = doc.selection().transform(|range| {
652640 Range::new(
653641 range.from(),
654642 graphemes::prev_grapheme_boundary(text, range.to()),
655643 )
656644 });
657− view.doc.set_selection(selection);
645+ doc.set_selection(selection);
658646
659− view.doc.restore_cursor = false;
647+ doc.restore_cursor = false;
660648 }
661649}
662650
663651pub fn goto_mode(cx: &mut Context) {
664− cx.view().doc.mode = Mode::Goto;
652+ cx.doc().mode = Mode::Goto;
665653}
666654
667655// NOTE: Transactions in this module get appended to history when we switch back to normal mode.
@@ -670,9 +658,9 @@ pub mod insert {
670658 // TODO: insert means add text just before cursor, on exit we should be on the last letter.
671659 pub fn insert_char(cx: &mut Context, c: char) {
672660 let c = Tendril::from_char(c);
673− let transaction = Transaction::insert(&cx.view().doc.state, c);
661+ let transaction = Transaction::insert(&cx.doc().state, c);
674662
675− cx.view().doc.apply(&transaction);
663+ cx.doc().apply(&transaction);
676664 }
677665
678666 pub fn insert_tab(cx: &mut Context) {
@@ -680,11 +668,11 @@ pub mod insert {
680668 }
681669
682670 pub fn insert_newline(cx: &mut Context) {
683− let view = cx.view();
684− let transaction = Transaction::change_by_selection(&view.doc.state, |range| {
671+ let doc = cx.doc();
672+ let transaction = Transaction::change_by_selection(&doc.state, |range| {
685673 let indent_level = helix_core::indent::suggested_indent_for_pos(
686− view.doc.syntax.as_ref(),
687− &view.doc.state,
674+ doc.syntax.as_ref(),
675+ &doc.state,
688676 range.head,
689677 true,
690678 );
@@ -694,36 +682,36 @@ pub mod insert {
694682 text.push_str(&indent);
695683 (range.head, range.head, Some(text.into()))
696684 });
697− view.doc.apply(&transaction);
685+ doc.apply(&transaction);
698686 }
699687
700688 // TODO: handle indent-aware delete
701689 pub fn delete_char_backward(cx: &mut Context) {
702690 let count = cx.count;
703− let view = cx.view();
704− let text = &view.doc.text().slice(..);
705− let transaction = Transaction::change_by_selection(&view.doc.state, |range| {
691+ let doc = cx.doc();
692+ let text = &doc.text().slice(..);
693+ let transaction = Transaction::change_by_selection(&doc.state, |range| {
706694 (
707695 graphemes::nth_prev_grapheme_boundary(text, range.head, count),
708696 range.head,
709697 None,
710698 )
711699 });
712− view.doc.apply(&transaction);
700+ doc.apply(&transaction);
713701 }
714702
715703 pub fn delete_char_forward(cx: &mut Context) {
716704 let count = cx.count;
717− let view = cx.view();
718− let text = &view.doc.text().slice(..);
719− let transaction = Transaction::change_by_selection(&view.doc.state, |range| {
705+ let doc = cx.doc();
706+ let text = &doc.text().slice(..);
707+ let transaction = Transaction::change_by_selection(&doc.state, |range| {
720708 (
721709 range.head,
722710 graphemes::nth_next_grapheme_boundary(text, range.head, count),
723711 None,
724712 )
725713 });
726− view.doc.apply(&transaction);
714+ doc.apply(&transaction);
727715 }
728716}
729717
@@ -737,23 +725,22 @@ pub fn insert_char_prompt(prompt: &mut Prompt, c: char) {
737725// storing it?
738726
739727pub fn undo(cx: &mut Context) {
740− cx.view().doc.undo();
728+ cx.doc().undo();
741729}
742730
743731pub fn redo(cx: &mut Context) {
744− cx.view().doc.redo();
732+ cx.doc().redo();
745733}
746734
747735// Yank / Paste
748736
749737pub fn yank(cx: &mut Context) {
750738 // TODO: should selections be made end inclusive?
751− let view = cx.view();
752− let values = view
753− .doc
739+ let doc = cx.doc();
740+ let values = doc
754741 .state
755742 .selection()
756− .fragments(&view.doc.text().slice(..))
743+ .fragments(&doc.text().slice(..))
757744 .map(|cow| cow.into_owned())
758745 .collect();
759746
@@ -791,34 +778,34 @@ pub fn paste(cx: &mut Context) {
791778
792779 let mut values = values.into_iter().map(Tendril::from).chain(repeat);
793780
794− let view = cx.view();
781+ let doc = cx.doc();
795782
796783 let transaction = if linewise {
797784 // paste on the next line
798785 // TODO: can simply take a range + modifier and compute the right pos without ifs
799− let text = view.doc.text();
800− Transaction::change_by_selection(&view.doc.state, |range| {
786+ let text = doc.text();
787+ Transaction::change_by_selection(&doc.state, |range| {
801788 let line_end = text.line_to_char(text.char_to_line(range.head) + 1);
802789 (line_end, line_end, Some(values.next().unwrap()))
803790 })
804791 } else {
805− Transaction::change_by_selection(&view.doc.state, |range| {
792+ Transaction::change_by_selection(&doc.state, |range| {
806793 (range.head + 1, range.head + 1, Some(values.next().unwrap()))
807794 })
808795 };
809796
810− view.doc.apply(&transaction);
797+ doc.apply(&transaction);
811798 append_changes_to_history(cx);
812799 }
813800}
814801
815−fn get_lines(view: &View) -> Vec<usize> {
802+fn get_lines(doc: &Document) -> Vec<usize> {
816803 let mut lines = Vec::new();
817804
818805 // Get all line numbers
819− for range in view.doc.selection().ranges() {
820− let start = view.doc.text().char_to_line(range.from());
821− let end = view.doc.text().char_to_line(range.to());
806+ for range in doc.selection().ranges() {
807+ let start = doc.text().char_to_line(range.from());
808+ let end = doc.text().char_to_line(range.to());
822809
823810 for line in start..=end {
824811 lines.push(line)
@@ -830,30 +817,30 @@ fn get_lines(view: &View) -> Vec<usize> {
830817}
831818
832819pub fn indent(cx: &mut Context) {
833− let lines = get_lines(cx.view());
820+ let doc = cx.doc();
821+ let lines = get_lines(doc);
834822
835823 // Indent by one level
836824 let indent = Tendril::from(" ".repeat(TAB_WIDTH));
837825
838− let view = cx.view();
839−
840826 let transaction = Transaction::change(
841− &view.doc.state,
827+ &doc.state,
842828 lines.into_iter().map(|line| {
843− let pos = view.doc.text().line_to_char(line);
829+ let pos = doc.text().line_to_char(line);
844830 (pos, pos, Some(indent.clone()))
845831 }),
846832 );
847− cx.view().doc.apply(&transaction);
833+ cx.doc().apply(&transaction);
848834 append_changes_to_history(cx);
849835}
850836
851837pub fn unindent(cx: &mut Context) {
852− let lines = get_lines(cx.view());
838+ let doc = cx.doc();
839+ let lines = get_lines(doc);
853840 let mut changes = Vec::with_capacity(lines.len());
854841
855842 for line_idx in lines {
856− let line = cx.view().doc.text().line(line_idx);
843+ let line = doc.text().line(line_idx);
857844 let mut width = 0;
858845
859846 for ch in line.chars() {
@@ -869,14 +856,14 @@ pub fn unindent(cx: &mut Context) {
869856 }
870857
871858 if width > 0 {
872− let start = cx.view().doc.text().line_to_char(line_idx);
859+ let start = doc.text().line_to_char(line_idx);
873860 changes.push((start, start + width, None))
874861 }
875862 }
876863
877− let transaction = Transaction::change(&cx.view().doc.state, changes.into_iter());
864+ let transaction = Transaction::change(&doc.state, changes.into_iter());
878865
879− cx.view().doc.apply(&transaction);
866+ doc.apply(&transaction);
880867 append_changes_to_history(cx);
881868}
882869
@@ -891,7 +878,7 @@ pub fn save(cx: &mut Context) {
891878 // Spawns an async task to actually do the saving. This way we prevent blocking.
892879
893880 // TODO: handle save errors somehow?
894− cx.executor.spawn(cx.view().doc.save()).detach();
881+ cx.executor.spawn(cx.doc().save()).detach();
895882}
896883
897884pub fn completion(cx: &mut Context) {
@@ -902,15 +889,14 @@ pub fn completion(cx: &mut Context) {
902889 .unwrap();
903890 use log::info;
904891
905− let view = cx.view();
892+ let doc = cx.doc();
906893
907894 // TODO: blocking here is not ideal
908− let pos =
909− helix_lsp::util::pos_to_lsp_pos(&view.doc.text().slice(..), view.doc.selection().cursor());
895+ let pos = helix_lsp::util::pos_to_lsp_pos(&doc.text().slice(..), doc.selection().cursor());
910896
911897 // TODO: handle fails
912− let res = smol::block_on(language_server.completion(cx.view().doc.identifier(), pos))
913− .unwrap_or_default();
898+ let res =
899+ smol::block_on(language_server.completion(cx.doc().identifier(), pos)).unwrap_or_default();
914900
915901 // TODO: if no completion, show some message or something
916902 if !res.is_empty() {
@@ -946,10 +932,9 @@ pub fn completion(cx: &mut Context) {
946932 }
947933 }
948934
949− let view = editor.view_mut();
950− let transaction =
951− util::generate_transaction_from_edits(&view.doc.state, vec![edit]);
952− view.doc.apply(&transaction);
935+ let doc = &mut editor.view_mut().doc;
936+ let transaction = util::generate_transaction_from_edits(&doc.state, vec![edit]);
937+ doc.apply(&transaction);
953938 // TODO: append_changes_to_history(cx); if not in insert mode?
954939 },
955940 );