@@ -55,6 +55,11 @@ impl<'a> Context<'a> {
5555 &mut self.editor.documents[id]
5656 }
5757
58+ #[inline]
59+ pub fn current(&mut self) -> (&mut View, &mut Document) {
60+ self.editor.current()
61+ }
62+
5863 /// Push a new component onto the compositor.
5964 pub fn push_layer(&mut self, mut component: Box<dyn Component>) {
6065 self.callback = Some(Box::new(
@@ -103,10 +108,9 @@ pub type Command = fn(cx: &mut Context);
103108
104109pub fn move_char_left(cx: &mut Context) {
105110 let count = cx.count;
106− let view_id = cx.view_id;
107− let doc = cx.doc();
111+ let (view, doc) = cx.current();
108112 let text = doc.text().slice(..);
109− let selection = doc.selection(view_id).transform(|range| {
113+ let selection = doc.selection(view.id).transform(|range| {
110114 movement::move_horizontally(
111115 text,
112116 range,
@@ -115,15 +119,14 @@ pub fn move_char_left(cx: &mut Context) {
115119 false, /* extend */
116120 )
117121 });
118− doc.set_selection(view_id, selection);
122+ doc.set_selection(view.id, selection);
119123}
120124
121125pub fn move_char_right(cx: &mut Context) {
122126 let count = cx.count;
123− let view_id = cx.view_id;
124− let doc = cx.doc();
127+ let (view, doc) = cx.current();
125128 let text = doc.text().slice(..);
126− let selection = doc.selection(view_id).transform(|range| {
129+ let selection = doc.selection(view.id).transform(|range| {
127130 movement::move_horizontally(
128131 text,
129132 range,
@@ -132,15 +135,14 @@ pub fn move_char_right(cx: &mut Context) {
132135 false, /* extend */
133136 )
134137 });
135− doc.set_selection(view_id, selection);
138+ doc.set_selection(view.id, selection);
136139}
137140
138141pub fn move_line_up(cx: &mut Context) {
139142 let count = cx.count;
140− let view_id = cx.view_id;
141− let doc = cx.doc();
143+ let (view, doc) = cx.current();
142144 let text = doc.text().slice(..);
143− let selection = doc.selection(view_id).transform(|range| {
145+ let selection = doc.selection(view.id).transform(|range| {
144146 movement::move_vertically(
145147 text,
146148 range,
@@ -149,15 +151,14 @@ pub fn move_line_up(cx: &mut Context) {
149151 false, /* extend */
150152 )
151153 });
152− doc.set_selection(view_id, selection);
154+ doc.set_selection(view.id, selection);
153155}
154156
155157pub fn move_line_down(cx: &mut Context) {
156158 let count = cx.count;
157− let view_id = cx.view_id;
158− let doc = cx.doc();
159+ let (view, doc) = cx.current();
159160 let text = doc.text().slice(..);
160− let selection = doc.selection(view_id).transform(|range| {
161+ let selection = doc.selection(view.id).transform(|range| {
161162 movement::move_vertically(
162163 text,
163164 range,
@@ -166,13 +167,12 @@ pub fn move_line_down(cx: &mut Context) {
166167 false, /* extend */
167168 )
168169 });
169− doc.set_selection(view_id, selection);
170+ doc.set_selection(view.id, selection);
170171}
171172
172173pub fn move_line_end(cx: &mut Context) {
173− let view_id = cx.view_id;
174− let doc = cx.doc();
175− let lines = selection_lines(doc.text(), doc.selection(view_id));
174+ let (view, doc) = cx.current();
175+ let lines = selection_lines(doc.text(), doc.selection(view.id));
176176
177177 let positions = lines
178178 .into_iter()
@@ -187,13 +187,12 @@ pub fn move_line_end(cx: &mut Context) {
187187
188188 let selection = Selection::new(positions.collect(), 0);
189189
190− doc.set_selection(view_id, selection);
190+ doc.set_selection(view.id, selection);
191191}
192192
193193pub fn move_line_start(cx: &mut Context) {
194− let view_id = cx.view_id;
195− let doc = cx.doc();
196− let lines = selection_lines(doc.text(), doc.selection(view_id));
194+ let (view, doc) = cx.current();
195+ let lines = selection_lines(doc.text(), doc.selection(view.id));
197196
198197 let positions = lines
199198 .into_iter()
@@ -205,7 +204,7 @@ pub fn move_line_start(cx: &mut Context) {
205204
206205 let selection = Selection::new(positions.collect(), 0);
207206
208− doc.set_selection(view_id, selection);
207+ doc.set_selection(view.id, selection);
209208}
210209
211210// TODO: move vs extend could take an extra type Extend/Move that would
@@ -214,101 +213,93 @@ pub fn move_line_start(cx: &mut Context) {
214213
215214pub fn move_next_word_start(cx: &mut Context) {
216215 let count = cx.count;
217− let view_id = cx.view_id;
218− let doc = cx.doc();
216+ let (view, doc) = cx.current();
219217 let text = doc.text().slice(..);
220218
221− let selection = doc.selection(view_id).transform(|range| {
219+ let selection = doc.selection(view.id).transform(|range| {
222220 let pos = movement::move_next_word_start(text, range.head, count);
223221 Range::new(pos, pos)
224222 });
225223
226− doc.set_selection(view_id, selection);
224+ doc.set_selection(view.id, selection);
227225}
228226
229227pub fn move_prev_word_start(cx: &mut Context) {
230228 let count = cx.count;
231− let view_id = cx.view_id;
232− let doc = cx.doc();
229+ let (view, doc) = cx.current();
233230 let text = doc.text().slice(..);
234231
235− let selection = doc.selection(view_id).transform(|range| {
232+ let selection = doc.selection(view.id).transform(|range| {
236233 let pos = movement::move_prev_word_start(text, range.head, count);
237234 Range::new(pos, pos)
238235 });
239236
240− doc.set_selection(view_id, selection);
237+ doc.set_selection(view.id, selection);
241238}
242239
243240pub fn move_next_word_end(cx: &mut Context) {
244241 let count = cx.count;
245− let view_id = cx.view_id;
246− let doc = cx.doc();
242+ let (view, doc) = cx.current();
247243 let text = doc.text().slice(..);
248244
249− let selection = doc.selection(view_id).transform(|range| {
245+ let selection = doc.selection(view.id).transform(|range| {
250246 let pos = movement::move_next_word_end(text, range.head, count);
251247 Range::new(pos, pos)
252248 });
253249
254− doc.set_selection(view_id, selection);
250+ doc.set_selection(view.id, selection);
255251}
256252
257253pub fn move_file_start(cx: &mut Context) {
258254 push_jump(cx);
259− let view_id = cx.view_id;
260− let doc = cx.doc();
261− doc.set_selection(view_id, Selection::point(0));
255+ let (view, doc) = cx.current();
256+ doc.set_selection(view.id, Selection::point(0));
262257}
263258
264259pub fn move_file_end(cx: &mut Context) {
265260 push_jump(cx);
266− let view_id = cx.view_id;
267− let doc = cx.doc();
261+ let (view, doc) = cx.current();
268262 let text = doc.text();
269263 let last_line = text.line_to_char(text.len_lines().saturating_sub(2));
270− doc.set_selection(view_id, Selection::point(last_line));
264+ doc.set_selection(view.id, Selection::point(last_line));
271265}
272266
273267pub fn extend_next_word_start(cx: &mut Context) {
274268 let count = cx.count;
275− let view_id = cx.view_id;
276− let doc = cx.doc();
269+ let (view, doc) = cx.current();
277270 let text = doc.text().slice(..);
278271
279− let selection = doc.selection(view_id).transform(|mut range| {
272+ let selection = doc.selection(view.id).transform(|mut range| {
280273 let pos = movement::move_next_word_start(text, range.head, count);
281274 Range::new(range.anchor, pos)
282275 });
283276
284− doc.set_selection(view_id, selection);
277+ doc.set_selection(view.id, selection);
285278}
286279
287280pub fn extend_prev_word_start(cx: &mut Context) {
288281 let count = cx.count;
289− let view_id = cx.view_id;
290− let doc = cx.doc();
282+ let (view, doc) = cx.current();
291283 let text = doc.text().slice(..);
292284
293− let selection = doc.selection(view_id).transform(|mut range| {
285+ let selection = doc.selection(view.id).transform(|mut range| {
294286 let pos = movement::move_prev_word_start(text, range.head, count);
295287 Range::new(range.anchor, pos)
296288 });
297− doc.set_selection(view_id, selection);
289+ doc.set_selection(view.id, selection);
298290}
299291
300292pub fn extend_next_word_end(cx: &mut Context) {
301293 let count = cx.count;
302− let view_id = cx.view_id;
303− let doc = cx.doc();
294+ let (view, doc) = cx.current();
304295 let text = doc.text().slice(..);
305296
306− let selection = doc.selection(view_id).transform(|mut range| {
297+ let selection = doc.selection(view.id).transform(|mut range| {
307298 let pos = movement::move_next_word_end(text, range.head, count);
308299 Range::new(range.anchor, pos)
309300 });
310301
311− doc.set_selection(view_id, selection);
302+ doc.set_selection(view.id, selection);
312303}
313304
314305#[inline]
@@ -329,11 +320,10 @@ where
329320 ..
330321 } = event
331322 {
332− let view_id = cx.view_id;
333− let doc = cx.doc();
323+ let (view, doc) = cx.current();
334324 let text = doc.text().slice(..);
335325
336− let selection = doc.selection(view_id).transform(|mut range| {
326+ let selection = doc.selection(view.id).transform(|mut range| {
337327 search::find_nth_next(text, ch, range.head, count, inclusive).map_or(range, |pos| {
338328 if extend {
339329 Range::new(range.anchor, pos)
@@ -345,7 +335,7 @@ where
345335 })
346336 });
347337
348− doc.set_selection(view_id, selection);
338+ doc.set_selection(view.id, selection);
349339 }
350340 })
351341}
@@ -432,24 +422,22 @@ pub fn replace(cx: &mut Context) {
432422 {
433423 let text = Tendril::from_char(ch);
434424
435− let view_id = cx.view_id;
436− let doc = cx.doc();
425+ let (view, doc) = cx.current();
437426
438427 let transaction =
439− Transaction::change_by_selection(doc.text(), doc.selection(view_id), |range| {
428+ Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
440429 (range.from(), range.to() + 1, Some(text.clone()))
441430 });
442431
443− doc.apply(&transaction, view_id);
444− doc.append_changes_to_history(view_id);
432+ doc.apply(&transaction, view.id);
433+ doc.append_changes_to_history(view.id);
445434 }
446435 })
447436}
448437
449438fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
450439 use Direction::*;
451− let view = cx.editor.view();
452− let doc = cx.editor.document(view.doc).unwrap();
440+ let (view, doc) = cx.current();
453441 let cursor = coords_at_pos(doc.text().slice(..), doc.selection(view.id).cursor());
454442 let doc_last_line = doc.text().len_lines() - 1;
455443
@@ -466,9 +454,6 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
466454 // cursor visual offset
467455 let cursor_off = cursor.row - view.first_line;
468456
469− // upgrade to mut reference
470− let view = cx.editor.view_mut();
471−
472457 view.first_line = match direction {
473458 Forward => view.first_line + offset,
474459 Backward => view.first_line.saturating_sub(offset),
@@ -481,17 +466,10 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
481466 last_line.saturating_sub(scrolloff),
482467 );
483468
484− let view_id = view.id;
485−
486− // view drops here
487−
488− // upgrade to mut reference
489− let doc = cx.doc();
490−
491469 let text = doc.text().slice(..);
492470 let pos = pos_at_coords(text, Position::new(line, cursor.col)); // this func will properly truncate to line end
493471
494− doc.set_selection(view_id, Selection::point(pos));
472+ doc.set_selection(view.id, Selection::point(pos));
495473}
496474
497475pub fn page_up(cx: &mut Context) {
@@ -520,10 +498,9 @@ pub fn half_page_down(cx: &mut Context) {
520498
521499pub fn extend_char_left(cx: &mut Context) {
522500 let count = cx.count;
523− let view_id = cx.view_id;
524− let doc = cx.doc();
501+ let (view, doc) = cx.current();
525502 let text = doc.text().slice(..);
526− let selection = doc.selection(view_id).transform(|range| {
503+ let selection = doc.selection(view.id).transform(|range| {
527504 movement::move_horizontally(
528505 text,
529506 range,
@@ -532,15 +509,14 @@ pub fn extend_char_left(cx: &mut Context) {
532509 true, /* extend */
533510 )
534511 });
535− doc.set_selection(view_id, selection);
512+ doc.set_selection(view.id, selection);
536513}
537514
538515pub fn extend_char_right(cx: &mut Context) {
539516 let count = cx.count;
540− let view_id = cx.view_id;
541− let doc = cx.doc();
517+ let (view, doc) = cx.current();
542518 let text = doc.text().slice(..);
543− let selection = doc.selection(view_id).transform(|range| {
519+ let selection = doc.selection(view.id).transform(|range| {
544520 movement::move_horizontally(
545521 text,
546522 range,
@@ -549,15 +525,14 @@ pub fn extend_char_right(cx: &mut Context) {
549525 true, /* extend */
550526 )
551527 });
552− doc.set_selection(view_id, selection);
528+ doc.set_selection(view.id, selection);
553529}
554530
555531pub fn extend_line_up(cx: &mut Context) {
556532 let count = cx.count;
557− let view_id = cx.view_id;
558− let doc = cx.doc();
533+ let (view, doc) = cx.current();
559534 let text = doc.text().slice(..);
560− let selection = doc.selection(view_id).transform(|range| {
535+ let selection = doc.selection(view.id).transform(|range| {
561536 movement::move_vertically(
562537 text,
563538 range,
@@ -566,15 +541,14 @@ pub fn extend_line_up(cx: &mut Context) {
566541 true, /* extend */
567542 )
568543 });
569− doc.set_selection(view_id, selection);
544+ doc.set_selection(view.id, selection);
570545}
571546
572547pub fn extend_line_down(cx: &mut Context) {
573548 let count = cx.count;
574− let view_id = cx.view_id;
575− let doc = cx.doc();
549+ let (view, doc) = cx.current();
576550 let text = doc.text().slice(..);
577− let selection = doc.selection(view_id).transform(|range| {
551+ let selection = doc.selection(view.id).transform(|range| {
578552 movement::move_vertically(
579553 text,
580554 range,
@@ -583,15 +557,14 @@ pub fn extend_line_down(cx: &mut Context) {
583557 true, /* extend */
584558 )
585559 });
586− doc.set_selection(view_id, selection);
560+ doc.set_selection(view.id, selection);
587561}
588562
589563pub fn select_all(cx: &mut Context) {
590− let view_id = cx.view_id;
591− let doc = cx.doc();
564+ let (view, doc) = cx.current();
592565
593566 let end = doc.text().len_chars().saturating_sub(1);
594− doc.set_selection(view_id, Selection::single(0, end))
567+ doc.set_selection(view.id, Selection::single(0, end))
595568}
596569
597570pub fn select_regex(cx: &mut Context) {
@@ -619,14 +592,13 @@ pub fn split_selection(cx: &mut Context) {
619592}
620593
621594pub fn split_selection_on_newline(cx: &mut Context) {
622− let view_id = cx.view_id;
623− let doc = cx.doc();
595+ let (view, doc) = cx.current();
624596 let text = doc.text().slice(..);
625597 // only compile the regex once
626598 #[allow(clippy::trivial_regex)]
627599 static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\n").unwrap());
628− let selection = selection::split_on_matches(text, doc.selection(view_id), ®EX);
629− doc.set_selection(view_id, selection);
600+ let selection = selection::split_on_matches(text, doc.selection(view.id), ®EX);
601+ doc.set_selection(view.id, selection);
630602}
631603
632604// search: searches for the first occurence in file, provides a prompt
@@ -685,10 +657,9 @@ pub fn search_next(cx: &mut Context) {
685657}
686658
687659pub fn search_selection(cx: &mut Context) {
688− let view_id = cx.view_id;
689− let doc = cx.doc();
660+ let (view, doc) = cx.current();
690661 let contents = doc.text().slice(..);
691− let query = doc.selection(view_id).primary().fragment(contents);
662+ let query = doc.selection(view.id).primary().fragment(contents);
692663 let regex = regex::escape(&query);
693664 register::set('\\', vec![regex]);
694665 search_next(cx);
@@ -702,24 +673,22 @@ pub fn search_selection(cx: &mut Context) {
702673
703674pub fn select_line(cx: &mut Context) {
704675 let count = cx.count;
705− let view_id = cx.view_id;
706− let doc = cx.doc();
676+ let (view, doc) = cx.current();
707677
708− let pos = doc.selection(view_id).primary();
678+ let pos = doc.selection(view.id).primary();
709679 let text = doc.text();
710680
711681 let line = text.char_to_line(pos.head);
712682 let start = text.line_to_char(line);
713683 let end = text.line_to_char(line + count).saturating_sub(1);
714684
715− doc.set_selection(view_id, Selection::single(start, end));
685+ doc.set_selection(view.id, Selection::single(start, end));
716686}
717687pub fn extend_line(cx: &mut Context) {
718− let view_id = cx.view_id;
719688 let count = cx.count;
720− let doc = cx.doc();
689+ let (view, doc) = cx.current();
721690
722− let pos = doc.selection(view_id).primary();
691+ let pos = doc.selection(view.id).primary();
723692 let text = doc.text();
724693
725694 let line_start = text.char_to_line(pos.anchor);
@@ -732,7 +701,7 @@ pub fn extend_line(cx: &mut Context) {
732701 let start = text.line_to_char(line_start);
733702 let end = text.line_to_char(line + 1).saturating_sub(1);
734703
735− doc.set_selection(view_id, Selection::single(start, end));
704+ doc.set_selection(view.id, Selection::single(start, end));
736705}
737706
738707// heuristic: append changes to history after each command, unless we're in insert mode
@@ -746,38 +715,34 @@ fn _delete_selection(doc: &mut Document, view_id: ViewId) {
746715}
747716
748717pub fn delete_selection(cx: &mut Context) {
749− let view_id = cx.view_id;
750− let doc = cx.doc();
751− _delete_selection(doc, view_id);
718+ let (view, doc) = cx.current();
719+ _delete_selection(doc, view.id);
752720
753− doc.append_changes_to_history(view_id);
721+ doc.append_changes_to_history(view.id);
754722}
755723
756724pub fn change_selection(cx: &mut Context) {
757− let view_id = cx.view_id;
758− let doc = cx.doc();
759− _delete_selection(doc, view_id);
725+ let (view, doc) = cx.current();
726+ _delete_selection(doc, view.id);
760727 enter_insert_mode(doc);
761728}
762729
763730pub fn collapse_selection(cx: &mut Context) {
764− let view_id = cx.view_id;
765− let doc = cx.doc();
731+ let (view, doc) = cx.current();
766732 let selection = doc
767− .selection(view_id)
733+ .selection(view.id)
768734 .transform(|range| Range::new(range.head, range.head));
769735
770− doc.set_selection(view_id, selection);
736+ doc.set_selection(view.id, selection);
771737}
772738
773739pub fn flip_selections(cx: &mut Context) {
774− let view_id = cx.view_id;
775− let doc = cx.doc();
740+ let (view, doc) = cx.current();
776741 let selection = doc
777− .selection(view_id)
742+ .selection(view.id)
778743 .transform(|range| Range::new(range.head, range.anchor));
779744
780− doc.set_selection(view_id, selection);
745+ doc.set_selection(view.id, selection);
781746}
782747
783748fn enter_insert_mode(doc: &mut Document) {
@@ -786,31 +751,29 @@ fn enter_insert_mode(doc: &mut Document) {
786751
787752// inserts at the start of each selection
788753pub fn insert_mode(cx: &mut Context) {
789− let view_id = cx.view_id;
790− let doc = cx.doc();
754+ let (view, doc) = cx.current();
791755 enter_insert_mode(doc);
792756
793757 let selection = doc
794− .selection(view_id)
758+ .selection(view.id)
795759 .transform(|range| Range::new(range.to(), range.from()));
796− doc.set_selection(view_id, selection);
760+ doc.set_selection(view.id, selection);
797761}
798762
799763// inserts at the end of each selection
800764pub fn append_mode(cx: &mut Context) {
801− let view_id = cx.view_id;
802− let doc = cx.doc();
765+ let (view, doc) = cx.current();
803766 enter_insert_mode(doc);
804767 doc.restore_cursor = true;
805768
806769 let text = doc.text().slice(..);
807− let selection = doc.selection(view_id).transform(|range| {
770+ let selection = doc.selection(view.id).transform(|range| {
808771 Range::new(
809772 range.from(),
810773 graphemes::next_grapheme_boundary(text, range.to()), // to() + next char
811774 )
812775 });
813− doc.set_selection(view_id, selection);
776+ doc.set_selection(view.id, selection);
814777}
815778
816779const COMMAND_LIST: &[&str] = &["write", "open", "quit"];
@@ -970,27 +933,25 @@ pub fn prepend_to_line(cx: &mut Context) {
970933pub fn append_to_line(cx: &mut Context) {
971934 move_line_end(cx);
972935
973− let view_id = cx.view_id;
974− let doc = cx.doc();
936+ let (view, doc) = cx.current();
975937 enter_insert_mode(doc);
976938
977939 // offset by another 1 char since move_line_end will position on the last char, we want to
978940 // append past that
979− let selection = doc.selection(view_id).transform(|range| {
941+ let selection = doc.selection(view.id).transform(|range| {
980942 let pos = range.head + 1;
981943 Range::new(pos, pos)
982944 });
983− doc.set_selection(view_id, selection);
945+ doc.set_selection(view.id, selection);
984946}
985947
986948// o inserts a new line after each line with a selection
987949pub fn open_below(cx: &mut Context) {
988− let view_id = cx.view_id;
989950 let count = cx.count;
990− let doc = cx.doc();
951+ let (view, doc) = cx.current();
991952 enter_insert_mode(doc);
992953
993− let lines = selection_lines(doc.text(), doc.selection(view_id));
954+ let lines = selection_lines(doc.text(), doc.selection(view.id));
994955
995956 let positions = lines.into_iter().map(|index| {
996957 // adjust all positions to the end of the line (next line minus one)
@@ -1032,17 +993,16 @@ pub fn open_below(cx: &mut Context) {
1032993 let transaction =
1033994 Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
1034995
1035− doc.apply(&transaction, view_id);
996+ doc.apply(&transaction, view.id);
1036997}
1037998
1038999// O inserts a new line before each line with a selection
10391000pub fn open_above(cx: &mut Context) {
1040− let view_id = cx.view_id;
10411001 let count = cx.count;
1042− let doc = cx.doc();
1002+ let (view, doc) = cx.current();
10431003 enter_insert_mode(doc);
10441004
1045− let lines = selection_lines(doc.text(), doc.selection(view_id));
1005+ let lines = selection_lines(doc.text(), doc.selection(view.id));
10461006
10471007 let positions = lines.into_iter().map(|index| {
10481008 // adjust all positions to the end of the previous line
@@ -1085,27 +1045,26 @@ pub fn open_above(cx: &mut Context) {
10851045 let transaction =
10861046 Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
10871047
1088− doc.apply(&transaction, view_id);
1048+ doc.apply(&transaction, view.id);
10891049}
10901050
10911051pub fn normal_mode(cx: &mut Context) {
1092− let view_id = cx.view_id;
1093− let doc = cx.doc();
1052+ let (view, doc) = cx.current();
10941053
10951054 doc.mode = Mode::Normal;
10961055
1097− doc.append_changes_to_history(view_id);
1056+ doc.append_changes_to_history(view.id);
10981057
10991058 // if leaving append mode, move cursor back by 1
11001059 if doc.restore_cursor {
11011060 let text = doc.text().slice(..);
1102− let selection = doc.selection(view_id).transform(|range| {
1061+ let selection = doc.selection(view.id).transform(|range| {
11031062 Range::new(
11041063 range.from(),
11051064 graphemes::prev_grapheme_boundary(text, range.to()),
11061065 )
11071066 });
1108− doc.set_selection(view_id, selection);
1067+ doc.set_selection(view.id, selection);
11091068
11101069 doc.restore_cursor = false;
11111070 }
@@ -1113,16 +1072,12 @@ pub fn normal_mode(cx: &mut Context) {
11131072
11141073// Store a jump on the jumplist.
11151074fn push_jump(cx: &mut Context) {
1116− let jump = {
1117− let view_id = cx.view_id;
1118− let doc = cx.doc();
1119− (doc.id(), doc.selection(view_id).clone())
1120− };
1121− cx.view().jumps.push(jump);
1075+ let (view, doc) = cx.current();
1076+ let jump = { (doc.id(), doc.selection(view.id).clone()) };
1077+ view.jumps.push(jump);
11221078}
11231079
11241080pub fn goto_mode(cx: &mut Context) {
1125− let view_id = cx.view_id;
11261081 let count = cx.count;
11271082
11281083 if count > 1 {
@@ -1130,9 +1085,9 @@ pub fn goto_mode(cx: &mut Context) {
11301085
11311086 // TODO: can't go to line 1 since we can't distinguish between g and 1g, g gets converted
11321087 // to 1g
1133− let doc = cx.doc();
1088+ let (view, doc) = cx.current();
11341089 let pos = doc.text().line_to_char(count - 1);
1135− doc.set_selection(view_id, Selection::point(pos));
1090+ doc.set_selection(view.id, Selection::point(pos));
11361091 return;
11371092 }
11381093
@@ -1173,11 +1128,10 @@ fn _goto(cx: &mut Context, locations: Vec<lsp::Location>) {
11731128 let id = editor
11741129 .open(PathBuf::from(location.uri.path()), action)
11751130 .expect("editor.open failed");
1176− let view_id = editor.view().id;
1177− let doc = &mut editor.documents[id];
1131+ let (view, doc) = editor.current();
11781132 let definition_pos = location.range.start;
11791133 let new_pos = helix_lsp::util::lsp_pos_to_pos(doc.text(), definition_pos);
1180− doc.set_selection(view_id, Selection::point(new_pos));
1134+ doc.set_selection(view.id, Selection::point(new_pos));
11811135 }
11821136
11831137 match locations.as_slice() {
@@ -1201,15 +1155,14 @@ fn _goto(cx: &mut Context, locations: Vec<lsp::Location>) {
12011155}
12021156
12031157pub fn goto_definition(cx: &mut Context) {
1204− let view_id = cx.view_id;
1205− let doc = cx.doc();
1158+ let (view, doc) = cx.current();
12061159 let language_server = match doc.language_server() {
12071160 Some(language_server) => language_server,
12081161 None => return,
12091162 };
12101163
12111164 // TODO: blocking here is not ideal
1212− let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view_id).cursor());
1165+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor());
12131166
12141167 // TODO: handle fails
12151168 let res =
@@ -1218,15 +1171,14 @@ pub fn goto_definition(cx: &mut Context) {
12181171}
12191172
12201173pub fn goto_type_definition(cx: &mut Context) {
1221− let view_id = cx.view_id;
1222− let doc = cx.doc();
1174+ let (view, doc) = cx.current();
12231175 let language_server = match doc.language_server() {
12241176 Some(language_server) => language_server,
12251177 None => return,
12261178 };
12271179
12281180 // TODO: blocking here is not ideal
1229− let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view_id).cursor());
1181+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor());
12301182
12311183 // TODO: handle fails
12321184 let res = smol::block_on(language_server.goto_type_definition(doc.identifier(), pos))
@@ -1235,15 +1187,14 @@ pub fn goto_type_definition(cx: &mut Context) {
12351187}
12361188
12371189pub fn goto_implementation(cx: &mut Context) {
1238− let view_id = cx.view_id;
1239− let doc = cx.doc();
1190+ let (view, doc) = cx.current();
12401191 let language_server = match doc.language_server() {
12411192 Some(language_server) => language_server,
12421193 None => return,
12431194 };
12441195
12451196 // TODO: blocking here is not ideal
1246− let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view_id).cursor());
1197+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor());
12471198
12481199 // TODO: handle fails
12491200 let res = smol::block_on(language_server.goto_implementation(doc.identifier(), pos))
@@ -1252,15 +1203,14 @@ pub fn goto_implementation(cx: &mut Context) {
12521203}
12531204
12541205pub fn goto_reference(cx: &mut Context) {
1255− let view_id = cx.view_id;
1256− let doc = cx.doc();
1206+ let (view, doc) = cx.current();
12571207 let language_server = match doc.language_server() {
12581208 Some(language_server) => language_server,
12591209 None => return,
12601210 };
12611211
12621212 // TODO: blocking here is not ideal
1263− let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view_id).cursor());
1213+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor());
12641214
12651215 // TODO: handle fails
12661216 let res =
@@ -1269,8 +1219,7 @@ pub fn goto_reference(cx: &mut Context) {
12691219}
12701220
12711221pub fn signature_help(cx: &mut Context) {
1272− let view_id = cx.view_id;
1273− let doc = cx.doc();
1222+ let (view, doc) = cx.current();
12741223
12751224 let language_server = match doc.language_server() {
12761225 Some(language_server) => language_server,
@@ -1278,7 +1227,7 @@ pub fn signature_help(cx: &mut Context) {
12781227 };
12791228
12801229 // TODO: blocking here is not ideal
1281− let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view_id).cursor());
1230+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor());
12821231
12831232 // TODO: handle fails
12841233
@@ -1371,21 +1320,20 @@ pub mod insert {
13711320
13721321 // TODO: insert means add text just before cursor, on exit we should be on the last letter.
13731322 pub fn insert_char(cx: &mut Context, c: char) {
1374− let view_id = cx.view_id;
1375− let doc = cx.doc();
1323+ let (view, doc) = cx.current();
13761324
13771325 // run through insert hooks, stopping on the first one that returns Some(t)
13781326 for hook in HOOKS {
1379− if let Some(transaction) = hook(doc.text(), doc.selection(view_id), c) {
1380− doc.apply(&transaction, view_id);
1327+ if let Some(transaction) = hook(doc.text(), doc.selection(view.id), c) {
1328+ doc.apply(&transaction, view.id);
13811329 return;
13821330 }
13831331 }
13841332
13851333 let t = Tendril::from_char(c);
1386− let transaction = Transaction::insert(doc.text(), doc.selection(view_id), t);
1334+ let transaction = Transaction::insert(doc.text(), doc.selection(view.id), t);
13871335
1388− doc.apply(&transaction, view_id);
1336+ doc.apply(&transaction, view.id);
13891337
13901338 // TODO: need a post insert hook too for certain triggers (autocomplete, signature help, etc)
13911339 // this could also generically look at Transaction, but it's a bit annoying to look at
@@ -1396,22 +1344,20 @@ pub mod insert {
13961344 }
13971345
13981346 pub fn insert_tab(cx: &mut Context) {
1399− let view_id = cx.view_id;
1400− let doc = cx.doc();
1347+ let (view, doc) = cx.current();
14011348 // TODO: round out to nearest indentation level (for example a line with 3 spaces should
14021349 // indent by one to reach 4 spaces).
14031350
14041351 let indent = Tendril::from(doc.indent_unit());
1405− let transaction = Transaction::insert(doc.text(), doc.selection(view_id), indent);
1406− doc.apply(&transaction, view_id);
1352+ let transaction = Transaction::insert(doc.text(), doc.selection(view.id), indent);
1353+ doc.apply(&transaction, view.id);
14071354 }
14081355
14091356 pub fn insert_newline(cx: &mut Context) {
1410− let view_id = cx.view_id;
1411− let doc = cx.doc();
1357+ let (view, doc) = cx.current();
14121358 let text = doc.text().slice(..);
14131359 let transaction =
1414− Transaction::change_by_selection(doc.text(), doc.selection(view_id), |range| {
1360+ Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
14151361 // TODO: offset range.head by 1? when calculating?
14161362 let indent_level = helix_core::indent::suggested_indent_for_pos(
14171363 doc.syntax(),
@@ -1425,40 +1371,39 @@ pub mod insert {
14251371 text.push_str(&indent);
14261372 (range.head, range.head, Some(text.into()))
14271373 });
1428− doc.apply(&transaction, view_id);
1374+ doc.apply(&transaction, view.id);
14291375 }
14301376
14311377 // TODO: handle indent-aware delete
14321378 pub fn delete_char_backward(cx: &mut Context) {
1433− let view_id = cx.view_id;
14341379 let count = cx.count;
1435− let doc = cx.doc();
1380+ let (view, doc) = cx.current();
14361381 let text = doc.text().slice(..);
14371382 let transaction =
1438− Transaction::change_by_selection(doc.text(), doc.selection(view_id), |range| {
1383+ Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
14391384 (
14401385 graphemes::nth_prev_grapheme_boundary(text, range.head, count),
14411386 range.head,
14421387 None,
14431388 )
14441389 });
1445− doc.apply(&transaction, view_id);
1390+ doc.apply(&transaction, view.id);
14461391 }
14471392
14481393 pub fn delete_char_forward(cx: &mut Context) {
1449− let view_id = cx.view_id;
14501394 let count = cx.count;
14511395 let doc = cx.doc();
1396+ let (view, doc) = cx.current();
14521397 let text = doc.text().slice(..);
14531398 let transaction =
1454− Transaction::change_by_selection(doc.text(), doc.selection(view_id), |range| {
1399+ Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
14551400 (
14561401 range.head,
14571402 graphemes::nth_next_grapheme_boundary(text, range.head, count),
14581403 None,
14591404 )
14601405 });
1461− doc.apply(&transaction, view_id);
1406+ doc.apply(&transaction, view.id);
14621407 }
14631408}
14641409
@@ -1481,10 +1426,9 @@ pub fn redo(cx: &mut Context) {
14811426
14821427pub fn yank(cx: &mut Context) {
14831428 // TODO: should selections be made end inclusive?
1484− let view_id = cx.view_id;
1485− let doc = cx.doc();
1429+ let (view, doc) = cx.current();
14861430 let values: Vec<String> = doc
1487− .selection(view_id)
1431+ .selection(view.id)
14881432 .fragments(doc.text().slice(..))
14891433 .map(Cow::into_owned)
14901434 .collect();
@@ -1527,25 +1471,24 @@ pub fn paste(cx: &mut Context) {
15271471
15281472 let mut values = values.into_iter().map(Tendril::from).chain(repeat);
15291473
1530− let view_id = cx.view_id;
1531− let doc = cx.doc();
1474+ let (view, doc) = cx.current();
15321475
15331476 let transaction = if linewise {
15341477 // paste on the next line
15351478 // TODO: can simply take a range + modifier and compute the right pos without ifs
15361479 let text = doc.text();
1537− Transaction::change_by_selection(doc.text(), doc.selection(view_id), |range| {
1480+ Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
15381481 let line_end = text.line_to_char(text.char_to_line(range.head) + 1);
15391482 (line_end, line_end, Some(values.next().unwrap()))
15401483 })
15411484 } else {
1542− Transaction::change_by_selection(doc.text(), doc.selection(view_id), |range| {
1485+ Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
15431486 (range.head + 1, range.head + 1, Some(values.next().unwrap()))
15441487 })
15451488 };
15461489
1547− doc.apply(&transaction, view_id);
1548− doc.append_changes_to_history(view_id);
1490+ doc.apply(&transaction, view.id);
1491+ doc.append_changes_to_history(view.id);
15491492 }
15501493}
15511494
@@ -1567,9 +1510,8 @@ fn get_lines(doc: &Document, view_id: ViewId) -> Vec<usize> {
15671510}
15681511
15691512pub fn indent(cx: &mut Context) {
1570− let view_id = cx.view_id;
1571− let doc = cx.doc();
1572− let lines = get_lines(doc, view_id);
1513+ let (view, doc) = cx.current();
1514+ let lines = get_lines(doc, view.id);
15731515
15741516 // Indent by one level
15751517 let indent = Tendril::from(doc.indent_unit());
@@ -1581,14 +1523,13 @@ pub fn indent(cx: &mut Context) {
15811523 (pos, pos, Some(indent.clone()))
15821524 }),
15831525 );
1584− doc.apply(&transaction, view_id);
1585− doc.append_changes_to_history(view_id);
1526+ doc.apply(&transaction, view.id);
1527+ doc.append_changes_to_history(view.id);
15861528}
15871529
15881530pub fn unindent(cx: &mut Context) {
1589− let view_id = cx.view_id;
1590− let doc = cx.doc();
1591− let lines = get_lines(doc, view_id);
1531+ let (view, doc) = cx.current();
1532+ let lines = get_lines(doc, view.id);
15921533 let mut changes = Vec::with_capacity(lines.len());
15931534 let tab_width = doc.tab_width();
15941535
@@ -1616,14 +1557,13 @@ pub fn unindent(cx: &mut Context) {
16161557
16171558 let transaction = Transaction::change(doc.text(), changes.into_iter());
16181559
1619− doc.apply(&transaction, view_id);
1620− doc.append_changes_to_history(view_id);
1560+ doc.apply(&transaction, view.id);
1561+ doc.append_changes_to_history(view.id);
16211562}
16221563
16231564pub fn format_selections(cx: &mut Context) {
16241565 use helix_lsp::lsp;
1625− let view_id = cx.view_id;
1626− let doc = cx.doc();
1566+ let (view, doc) = cx.current();
16271567
16281568 // via lsp if available
16291569 // else via tree-sitter indentation calculations
@@ -1631,7 +1571,7 @@ pub fn format_selections(cx: &mut Context) {
16311571 // TODO: blocking here is not ideal
16321572
16331573 let ranges: Vec<lsp::Range> = doc
1634− .selection(view_id)
1574+ .selection(view.id)
16351575 .iter()
16361576 .map(|range| helix_lsp::util::range_to_lsp_range(doc.text(), *range))
16371577 .collect();
@@ -1653,23 +1593,22 @@ pub fn format_selections(cx: &mut Context) {
16531593
16541594 let transaction = helix_lsp::util::generate_transaction_from_edits(doc.text(), edits);
16551595
1656− doc.apply(&transaction, view_id);
1596+ doc.apply(&transaction, view.id);
16571597 }
16581598
1659− doc.append_changes_to_history(view_id);
1599+ doc.append_changes_to_history(view.id);
16601600}
16611601
16621602pub fn join_selections(cx: &mut Context) {
16631603 use movement::skip_over_next;
1664− let view_id = cx.view_id;
1665− let doc = cx.doc();
1604+ let (view, doc) = cx.current();
16661605 let text = doc.text();
16671606 let slice = doc.text().slice(..);
16681607
16691608 let mut changes = Vec::new();
16701609 let fragment = Tendril::from(" ");
16711610
1672− for selection in doc.selection(view_id) {
1611+ for selection in doc.selection(view.id) {
16731612 let start = text.char_to_line(selection.from());
16741613 let mut end = text.char_to_line(selection.to());
16751614 if start == end {
@@ -1700,8 +1639,8 @@ pub fn join_selections(cx: &mut Context) {
17001639 // TODO: select inserted spaces
17011640 // .with_selection(selection);
17021641
1703− doc.apply(&transaction, view_id);
1704− doc.append_changes_to_history(view_id);
1642+ doc.apply(&transaction, view.id);
1643+ doc.append_changes_to_history(view.id);
17051644}
17061645
17071646pub fn keep_selections(cx: &mut Context) {
@@ -1719,12 +1658,11 @@ pub fn keep_selections(cx: &mut Context) {
17191658}
17201659
17211660pub fn keep_primary_selection(cx: &mut Context) {
1722− let view_id = cx.view_id;
1723− let doc = cx.doc();
1661+ let (view, doc) = cx.current();
17241662
1725− let range = doc.selection(view_id).primary();
1663+ let range = doc.selection(view.id).primary();
17261664 let selection = Selection::single(range.anchor, range.head);
1727− doc.set_selection(view_id, selection);
1665+ doc.set_selection(view.id, selection);
17281666}
17291667
17301668//
@@ -1773,8 +1711,7 @@ pub fn completion(cx: &mut Context) {
17731711 // The prefix still has to satisfy `company-minimum-prefix-length' before that
17741712 // happens. The value of nil means no idle completion."
17751713
1776− let view_id = cx.view_id;
1777− let doc = cx.doc();
1714+ let (view, doc) = cx.current();
17781715
17791716 let language_server = match doc.language_server() {
17801717 Some(language_server) => language_server,
@@ -1782,13 +1719,13 @@ pub fn completion(cx: &mut Context) {
17821719 };
17831720
17841721 // TODO: blocking here is not ideal
1785− let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view_id).cursor());
1722+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor());
17861723
17871724 // TODO: handle fails
17881725
17891726 let res = smol::block_on(language_server.completion(doc.identifier(), pos)).unwrap();
17901727
1791− let trigger_offset = doc.selection(view_id).cursor();
1728+ let trigger_offset = doc.selection(view.id).cursor();
17921729
17931730 cx.callback(
17941731 res,
@@ -1825,8 +1762,7 @@ pub fn completion(cx: &mut Context) {
18251762pub fn hover(cx: &mut Context) {
18261763 use helix_lsp::lsp;
18271764
1828− let view_id = cx.view_id;
1829− let doc = cx.doc();
1765+ let (view, doc) = cx.current();
18301766
18311767 let language_server = match doc.language_server() {
18321768 Some(language_server) => language_server,
@@ -1837,7 +1773,7 @@ pub fn hover(cx: &mut Context) {
18371773
18381774 // TODO: blocking here is not ideal, make commands async fn?
18391775 // not like we can process additional input meanwhile though
1840− let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view_id).cursor());
1776+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor());
18411777
18421778 // TODO: handle fails
18431779 let res = smol::block_on(language_server.text_document_hover(doc.identifier(), pos))
@@ -1873,36 +1809,33 @@ pub fn next_view(cx: &mut Context) {
18731809
18741810// comments
18751811pub fn toggle_comments(cx: &mut Context) {
1876− let view_id = cx.view_id;
1877− let doc = cx.doc();
1878− let transaction = comment::toggle_line_comments(doc.text(), doc.selection(view_id));
1812+ let (view, doc) = cx.current();
1813+ let transaction = comment::toggle_line_comments(doc.text(), doc.selection(view.id));
18791814
1880− doc.apply(&transaction, view_id);
1881− doc.append_changes_to_history(view_id);
1815+ doc.apply(&transaction, view.id);
1816+ doc.append_changes_to_history(view.id);
18821817}
18831818
18841819// tree sitter node selection
18851820
18861821pub fn expand_selection(cx: &mut Context) {
1887− let view_id = cx.view_id;
1888− let doc = cx.doc();
1822+ let (view, doc) = cx.current();
18891823
18901824 if let Some(syntax) = doc.syntax() {
18911825 let text = doc.text().slice(..);
1892− let selection = object::expand_selection(syntax, text, doc.selection(view_id));
1893− doc.set_selection(view_id, selection);
1826+ let selection = object::expand_selection(syntax, text, doc.selection(view.id));
1827+ doc.set_selection(view.id, selection);
18941828 }
18951829}
18961830
18971831pub fn match_brackets(cx: &mut Context) {
1898− let view_id = cx.view_id;
1899− let doc = cx.doc();
1832+ let (view, doc) = cx.current();
19001833
19011834 if let Some(syntax) = doc.syntax() {
1902− let pos = doc.selection(view_id).cursor();
1835+ let pos = doc.selection(view.id).cursor();
19031836 if let Some(pos) = match_brackets::find(syntax, doc.text(), pos) {
19041837 let selection = Selection::point(pos);
1905− doc.set_selection(view_id, selection);
1838+ doc.set_selection(view.id, selection);
19061839 };
19071840 }
19081841}
@@ -1922,16 +1855,14 @@ pub fn jump_forward(cx: &mut Context) {
19221855
19231856pub fn jump_backward(cx: &mut Context) {
19241857 let count = cx.count;
1925− let view = cx.view();
1858+ let (view, doc) = cx.current();
19261859
19271860 if let Some((id, selection)) = view.jumps.backward(count) {
19281861 // TODO: position first_line so that main cursor is centered
19291862 view.first_line = 0;
19301863 view.doc = *id;
19311864 let selection = selection.clone();
1932− let view_id = view.id;
1933− let doc = cx.doc();
1934− doc.set_selection(view_id, selection);
1865+ doc.set_selection(view.id, selection);
19351866 };
19361867}
19371868