@@ -19,7 +19,7 @@ use std::path::{Path, PathBuf};
1919use helix_view::{
2020 document::Mode,
2121 view::{View, PADDING},
22− Document, DocumentId, Editor,
22+ Document, DocumentId, Editor, ViewId,
2323};
2424
2525use crossterm::event::{KeyCode, KeyEvent};
@@ -31,6 +31,7 @@ use crate::application::{LspCallbackWrapper, LspCallbacks};
3131pub struct Context<'a> {
3232 pub count: usize,
3333 pub editor: &'a mut Editor,
34+ pub view_id: ViewId,
3435
3536 pub callback: Option<crate::compositor::Callback>,
3637 pub on_next_key_callback: Option<Box<dyn FnOnce(&mut Context, KeyEvent)>>,
@@ -101,9 +102,10 @@ pub type Command = fn(cx: &mut Context);
101102
102103pub fn move_char_left(cx: &mut Context) {
103104 let count = cx.count;
105+ let view_id = cx.view_id;
104106 let doc = cx.doc();
105107 let text = doc.text().slice(..);
106− let selection = doc.selection().transform(|range| {
108+ let selection = doc.selection(view_id).transform(|range| {
107109 movement::move_horizontally(
108110 text,
109111 range,
@@ -112,14 +114,15 @@ pub fn move_char_left(cx: &mut Context) {
112114 false, /* extend */
113115 )
114116 });
115− doc.set_selection(selection);
117+ doc.set_selection(view_id, selection);
116118}
117119
118120pub fn move_char_right(cx: &mut Context) {
119121 let count = cx.count;
122+ let view_id = cx.view_id;
120123 let doc = cx.doc();
121124 let text = doc.text().slice(..);
122− let selection = doc.selection().transform(|range| {
125+ let selection = doc.selection(view_id).transform(|range| {
123126 movement::move_horizontally(
124127 text,
125128 range,
@@ -128,14 +131,15 @@ pub fn move_char_right(cx: &mut Context) {
128131 false, /* extend */
129132 )
130133 });
131− doc.set_selection(selection);
134+ doc.set_selection(view_id, selection);
132135}
133136
134137pub fn move_line_up(cx: &mut Context) {
135138 let count = cx.count;
139+ let view_id = cx.view_id;
136140 let doc = cx.doc();
137141 let text = doc.text().slice(..);
138− let selection = doc.selection().transform(|range| {
142+ let selection = doc.selection(view_id).transform(|range| {
139143 movement::move_vertically(
140144 text,
141145 range,
@@ -144,14 +148,15 @@ pub fn move_line_up(cx: &mut Context) {
144148 false, /* extend */
145149 )
146150 });
147− doc.set_selection(selection);
151+ doc.set_selection(view_id, selection);
148152}
149153
150154pub fn move_line_down(cx: &mut Context) {
151155 let count = cx.count;
156+ let view_id = cx.view_id;
152157 let doc = cx.doc();
153158 let text = doc.text().slice(..);
154− let selection = doc.selection().transform(|range| {
159+ let selection = doc.selection(view_id).transform(|range| {
155160 movement::move_vertically(
156161 text,
157162 range,
@@ -160,12 +165,13 @@ pub fn move_line_down(cx: &mut Context) {
160165 false, /* extend */
161166 )
162167 });
163− doc.set_selection(selection);
168+ doc.set_selection(view_id, selection);
164169}
165170
166171pub fn move_line_end(cx: &mut Context) {
172+ let view_id = cx.view_id;
167173 let doc = cx.doc();
168− let lines = selection_lines(doc.text(), doc.selection());
174+ let lines = selection_lines(doc.text(), doc.selection(view_id));
169175
170176 let positions = lines
171177 .into_iter()
@@ -180,12 +186,13 @@ pub fn move_line_end(cx: &mut Context) {
180186
181187 let selection = Selection::new(positions.collect(), 0);
182188
183− doc.set_selection(selection);
189+ doc.set_selection(view_id, selection);
184190}
185191
186192pub fn move_line_start(cx: &mut Context) {
193+ let view_id = cx.view_id;
187194 let doc = cx.doc();
188− let lines = selection_lines(doc.text(), doc.selection());
195+ let lines = selection_lines(doc.text(), doc.selection(view_id));
189196
190197 let positions = lines
191198 .into_iter()
@@ -197,7 +204,7 @@ pub fn move_line_start(cx: &mut Context) {
197204
198205 let selection = Selection::new(positions.collect(), 0);
199206
200− doc.set_selection(selection);
207+ doc.set_selection(view_id, selection);
201208}
202209
203210// TODO: move vs extend could take an extra type Extend/Move that would
@@ -206,93 +213,101 @@ pub fn move_line_start(cx: &mut Context) {
206213
207214pub fn move_next_word_start(cx: &mut Context) {
208215 let count = cx.count;
216+ let view_id = cx.view_id;
209217 let doc = cx.doc();
210218 let text = doc.text().slice(..);
211219
212− let selection = doc.selection().transform(|range| {
220+ let selection = doc.selection(view_id).transform(|range| {
213221 let pos = movement::move_next_word_start(text, range.head, count);
214222 Range::new(pos, pos)
215223 });
216224
217− doc.set_selection(selection);
225+ doc.set_selection(view_id, selection);
218226}
219227
220228pub fn move_prev_word_start(cx: &mut Context) {
221229 let count = cx.count;
230+ let view_id = cx.view_id;
222231 let doc = cx.doc();
223232 let text = doc.text().slice(..);
224233
225− let selection = doc.selection().transform(|range| {
234+ let selection = doc.selection(view_id).transform(|range| {
226235 let pos = movement::move_prev_word_start(text, range.head, count);
227236 Range::new(pos, pos)
228237 });
229238
230− doc.set_selection(selection);
239+ doc.set_selection(view_id, selection);
231240}
232241
233242pub fn move_next_word_end(cx: &mut Context) {
234243 let count = cx.count;
244+ let view_id = cx.view_id;
235245 let doc = cx.doc();
236246 let text = doc.text().slice(..);
237247
238− let selection = doc.selection().transform(|range| {
248+ let selection = doc.selection(view_id).transform(|range| {
239249 let pos = movement::move_next_word_end(text, range.head, count);
240250 Range::new(pos, pos)
241251 });
242252
243− doc.set_selection(selection);
253+ doc.set_selection(view_id, selection);
244254}
245255
246256pub fn move_file_start(cx: &mut Context) {
247257 push_jump(cx);
258+ let view_id = cx.view_id;
248259 let doc = cx.doc();
249− doc.set_selection(Selection::point(0));
260+ doc.set_selection(view_id, Selection::point(0));
250261}
251262
252263pub fn move_file_end(cx: &mut Context) {
253264 push_jump(cx);
265+ let view_id = cx.view_id;
254266 let doc = cx.doc();
255267 let text = doc.text();
256268 let last_line = text.line_to_char(text.len_lines().saturating_sub(2));
257− doc.set_selection(Selection::point(last_line));
269+ doc.set_selection(view_id, Selection::point(last_line));
258270}
259271
260272pub fn extend_next_word_start(cx: &mut Context) {
261273 let count = cx.count;
274+ let view_id = cx.view_id;
262275 let doc = cx.doc();
263276 let text = doc.text().slice(..);
264277
265− let selection = doc.selection().transform(|mut range| {
278+ let selection = doc.selection(view_id).transform(|mut range| {
266279 let pos = movement::move_next_word_start(text, range.head, count);
267280 Range::new(range.anchor, pos)
268281 });
269282
270− doc.set_selection(selection);
283+ doc.set_selection(view_id, selection);
271284}
272285
273286pub fn extend_prev_word_start(cx: &mut Context) {
274287 let count = cx.count;
288+ let view_id = cx.view_id;
275289 let doc = cx.doc();
276290 let text = doc.text().slice(..);
277291
278− let selection = doc.selection().transform(|mut range| {
292+ let selection = doc.selection(view_id).transform(|mut range| {
279293 let pos = movement::move_prev_word_start(text, range.head, count);
280294 Range::new(range.anchor, pos)
281295 });
282− doc.set_selection(selection);
296+ doc.set_selection(view_id, selection);
283297}
284298
285299pub fn extend_next_word_end(cx: &mut Context) {
286300 let count = cx.count;
301+ let view_id = cx.view_id;
287302 let doc = cx.doc();
288303 let text = doc.text().slice(..);
289304
290− let selection = doc.selection().transform(|mut range| {
305+ let selection = doc.selection(view_id).transform(|mut range| {
291306 let pos = movement::move_next_word_end(text, range.head, count);
292307 Range::new(range.anchor, pos)
293308 });
294309
295− doc.set_selection(selection);
310+ doc.set_selection(view_id, selection);
296311}
297312
298313#[inline]
@@ -313,10 +328,11 @@ where
313328 ..
314329 } = event
315330 {
331+ let view_id = cx.view_id;
316332 let doc = cx.doc();
317333 let text = doc.text().slice(..);
318334
319− let selection = doc.selection().transform(|mut range| {
335+ let selection = doc.selection(view_id).transform(|mut range| {
320336 if let Some(pos) = search::find_nth_next(text, ch, range.head, count, inclusive) {
321337 if extend {
322338 Range::new(range.anchor, pos)
@@ -330,7 +346,7 @@ where
330346 }
331347 });
332348
333− doc.set_selection(selection);
349+ doc.set_selection(view_id, selection);
334350 }
335351 })
336352}
@@ -417,15 +433,16 @@ pub fn replace(cx: &mut Context) {
417433 {
418434 let text = Tendril::from_char(ch);
419435
436+ let view_id = cx.view_id;
420437 let doc = cx.doc();
421438
422439 let transaction =
423− Transaction::change_by_selection(doc.text(), doc.selection(), |range| {
440+ Transaction::change_by_selection(doc.text(), doc.selection(view_id), |range| {
424441 (range.from(), range.to() + 1, Some(text.clone()))
425442 });
426443
427− doc.apply(&transaction);
428− doc.append_changes_to_history();
444+ doc.apply(&transaction, view_id);
445+ doc.append_changes_to_history(view_id);
429446 }
430447 })
431448}
@@ -434,7 +451,7 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
434451 use Direction::*;
435452 let view = cx.editor.view();
436453 let doc = cx.editor.document(view.doc).unwrap();
437− let cursor = coords_at_pos(doc.text().slice(..), doc.selection().cursor());
454+ let cursor = coords_at_pos(doc.text().slice(..), doc.selection(view.id).cursor());
438455 let doc_last_line = doc.text().len_lines() - 1;
439456
440457 let last_line = view.last_line(doc);
@@ -465,6 +482,8 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
465482 last_line.saturating_sub(scrolloff),
466483 );
467484
485+ let view_id = view.id;
486+
468487 // view drops here
469488
470489 // upgrade to mut reference
@@ -473,7 +492,7 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
473492 let text = doc.text().slice(..);
474493 let pos = pos_at_coords(text, Position::new(line, cursor.col)); // this func will properly truncate to line end
475494
476− doc.set_selection(Selection::point(pos));
495+ doc.set_selection(view_id, Selection::point(pos));
477496}
478497
479498pub fn page_up(cx: &mut Context) {
@@ -502,9 +521,10 @@ pub fn half_page_down(cx: &mut Context) {
502521
503522pub fn extend_char_left(cx: &mut Context) {
504523 let count = cx.count;
524+ let view_id = cx.view_id;
505525 let doc = cx.doc();
506526 let text = doc.text().slice(..);
507− let selection = doc.selection().transform(|range| {
527+ let selection = doc.selection(view_id).transform(|range| {
508528 movement::move_horizontally(
509529 text,
510530 range,
@@ -513,14 +533,15 @@ pub fn extend_char_left(cx: &mut Context) {
513533 true, /* extend */
514534 )
515535 });
516− doc.set_selection(selection);
536+ doc.set_selection(view_id, selection);
517537}
518538
519539pub fn extend_char_right(cx: &mut Context) {
520540 let count = cx.count;
541+ let view_id = cx.view_id;
521542 let doc = cx.doc();
522543 let text = doc.text().slice(..);
523− let selection = doc.selection().transform(|range| {
544+ let selection = doc.selection(view_id).transform(|range| {
524545 movement::move_horizontally(
525546 text,
526547 range,
@@ -529,14 +550,15 @@ pub fn extend_char_right(cx: &mut Context) {
529550 true, /* extend */
530551 )
531552 });
532− doc.set_selection(selection);
553+ doc.set_selection(view_id, selection);
533554}
534555
535556pub fn extend_line_up(cx: &mut Context) {
536557 let count = cx.count;
558+ let view_id = cx.view_id;
537559 let doc = cx.doc();
538560 let text = doc.text().slice(..);
539− let selection = doc.selection().transform(|range| {
561+ let selection = doc.selection(view_id).transform(|range| {
540562 movement::move_vertically(
541563 text,
542564 range,
@@ -545,14 +567,15 @@ pub fn extend_line_up(cx: &mut Context) {
545567 true, /* extend */
546568 )
547569 });
548− doc.set_selection(selection);
570+ doc.set_selection(view_id, selection);
549571}
550572
551573pub fn extend_line_down(cx: &mut Context) {
552574 let count = cx.count;
575+ let view_id = cx.view_id;
553576 let doc = cx.doc();
554577 let text = doc.text().slice(..);
555− let selection = doc.selection().transform(|range| {
578+ let selection = doc.selection(view_id).transform(|range| {
556579 movement::move_vertically(
557580 text,
558581 range,
@@ -561,21 +584,24 @@ pub fn extend_line_down(cx: &mut Context) {
561584 true, /* extend */
562585 )
563586 });
564− doc.set_selection(selection);
587+ doc.set_selection(view_id, selection);
565588}
566589
567590pub fn select_all(cx: &mut Context) {
591+ let view_id = cx.view_id;
568592 let doc = cx.doc();
569593
570594 let end = doc.text().len_chars().saturating_sub(1);
571− doc.set_selection(Selection::single(0, end))
595+ doc.set_selection(view_id, Selection::single(0, end))
572596}
573597
574598pub fn select_regex(cx: &mut Context) {
575− let prompt = ui::regex_prompt(cx, "select:".to_string(), |doc, regex| {
599+ let view_id = cx.view_id;
600+ let prompt = ui::regex_prompt(cx, "select:".to_string(), move |doc, regex| {
576601 let text = doc.text().slice(..);
577− if let Some(selection) = selection::select_on_matches(text, doc.selection(), ®ex) {
578− doc.set_selection(selection);
602+ if let Some(selection) = selection::select_on_matches(text, doc.selection(view_id), ®ex)
603+ {
604+ doc.set_selection(view_id, selection);
579605 }
580606 });
581607
@@ -583,23 +609,25 @@ pub fn select_regex(cx: &mut Context) {
583609}
584610
585611pub fn split_selection(cx: &mut Context) {
586− let prompt = ui::regex_prompt(cx, "split:".to_string(), |doc, regex| {
612+ let view_id = cx.view_id;
613+ let prompt = ui::regex_prompt(cx, "split:".to_string(), move |doc, regex| {
587614 let text = doc.text().slice(..);
588− let selection = selection::split_on_matches(text, doc.selection(), ®ex);
589− doc.set_selection(selection);
615+ let selection = selection::split_on_matches(text, doc.selection(view_id), ®ex);
616+ doc.set_selection(view_id, selection);
590617 });
591618
592619 cx.push_layer(Box::new(prompt));
593620}
594621
595622pub fn split_selection_on_newline(cx: &mut Context) {
623+ let view_id = cx.view_id;
596624 let doc = cx.doc();
597625 let text = doc.text().slice(..);
598626 // only compile the regex once
599627 #[allow(clippy::trivial_regex)]
600628 static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\n").unwrap());
601− let selection = selection::split_on_matches(text, doc.selection(), ®EX);
602− doc.set_selection(selection);
629+ let selection = selection::split_on_matches(text, doc.selection(view_id), ®EX);
630+ doc.set_selection(view_id, selection);
603631}
604632
605633// search: searches for the first occurence in file, provides a prompt
@@ -609,9 +637,9 @@ pub fn split_selection_on_newline(cx: &mut Context) {
609637// I'd probably collect all the matches right now and store the current index. The cache needs
610638// wiping if input happens.
611639
612−fn _search(doc: &mut Document, contents: &str, regex: &Regex) {
640+fn _search(doc: &mut Document, view_id: ViewId, contents: &str, regex: &Regex) {
613641 let text = doc.text();
614− let start = doc.selection().cursor();
642+ let start = doc.selection(view_id).cursor();
615643
616644 // TODO: use find_at to find the next match after the cursor, loop around the end
617645 if let Some(mat) = regex.find_at(&contents, start) {
@@ -619,7 +647,7 @@ fn _search(doc: &mut Document, contents: &str, regex: &Regex) {
619647 let end = text.byte_to_char(mat.end());
620648 let selection = Selection::single(start, end - 1);
621649 // TODO: (first_match, regex) stuff in register?
622− doc.set_selection(selection);
650+ doc.set_selection(view_id, selection);
623651 };
624652}
625653
@@ -633,10 +661,11 @@ pub fn search(cx: &mut Context) {
633661 // feed chunks into the regex yet
634662 let contents = doc.text().slice(..).to_string();
635663
664+ let view_id = cx.view_id;
636665 let prompt = ui::regex_prompt(cx, "search:".to_string(), move |doc, regex| {
637666 let text = doc.text();
638− let start = doc.selection().cursor();
639− _search(doc, &contents, ®ex);
667+ let start = doc.selection(view_id).cursor();
668+ _search(doc, view_id, &contents, ®ex);
640669
641670 // TODO: only store on enter (accept), not update
642671 register::set('\\', vec![regex.as_str().to_string()]);
@@ -648,17 +677,19 @@ pub fn search(cx: &mut Context) {
648677pub fn search_next(cx: &mut Context) {
649678 if let Some(query) = register::get('\\') {
650679 let query = query.first().unwrap();
680+ let view_id = cx.view_id;
651681 let doc = cx.doc();
652682 let contents = doc.text().slice(..).to_string();
653683 let regex = Regex::new(&query).unwrap();
654− _search(doc, &contents, ®ex);
684+ _search(doc, view_id, &contents, ®ex);
655685 }
656686}
657687
658688pub fn search_selection(cx: &mut Context) {
689+ let view_id = cx.view_id;
659690 let doc = cx.doc();
660691 let contents = doc.text().slice(..);
661− let query = doc.selection().primary().fragment(contents);
692+ let query = doc.selection(view_id).primary().fragment(contents);
662693 let regex = regex::escape(&query);
663694 register::set('\\', vec![regex]);
664695 search_next(cx);
@@ -672,22 +703,24 @@ pub fn search_selection(cx: &mut Context) {
672703
673704pub fn select_line(cx: &mut Context) {
674705 let count = cx.count;
706+ let view_id = cx.view_id;
675707 let doc = cx.doc();
676708
677− let pos = doc.selection().primary();
709+ let pos = doc.selection(view_id).primary();
678710 let text = doc.text();
679711
680712 let line = text.char_to_line(pos.head);
681713 let start = text.line_to_char(line);
682714 let end = text.line_to_char(line + count).saturating_sub(1);
683715
684− doc.set_selection(Selection::single(start, end));
716+ doc.set_selection(view_id, Selection::single(start, end));
685717}
686718pub fn extend_line(cx: &mut Context) {
719+ let view_id = cx.view_id;
687720 let count = cx.count;
688721 let doc = cx.doc();
689722
690− let pos = doc.selection().primary();
723+ let pos = doc.selection(view_id).primary();
691724 let text = doc.text();
692725
693726 let line_start = text.char_to_line(pos.anchor);
@@ -700,47 +733,52 @@ pub fn extend_line(cx: &mut Context) {
700733 let start = text.line_to_char(line_start);
701734 let end = text.line_to_char(line + 1).saturating_sub(1);
702735
703− doc.set_selection(Selection::single(start, end));
736+ doc.set_selection(view_id, Selection::single(start, end));
704737}
705738
706739// heuristic: append changes to history after each command, unless we're in insert mode
707740
708−fn _delete_selection(doc: &mut Document) {
709− let transaction = Transaction::change_by_selection(doc.text(), doc.selection(), |range| {
710− (range.from(), range.to() + 1, None)
711− });
712− doc.apply(&transaction);
741+fn _delete_selection(doc: &mut Document, view_id: ViewId) {
742+ let transaction =
743+ Transaction::change_by_selection(doc.text(), doc.selection(view_id), |range| {
744+ (range.from(), range.to() + 1, None)
745+ });
746+ doc.apply(&transaction, view_id);
713747}
714748
715749pub fn delete_selection(cx: &mut Context) {
750+ let view_id = cx.view_id;
716751 let doc = cx.doc();
717− _delete_selection(doc);
752+ _delete_selection(doc, view_id);
718753
719− doc.append_changes_to_history();
754+ doc.append_changes_to_history(view_id);
720755}
721756
722757pub fn change_selection(cx: &mut Context) {
758+ let view_id = cx.view_id;
723759 let doc = cx.doc();
724− _delete_selection(doc);
760+ _delete_selection(doc, view_id);
725761 enter_insert_mode(doc);
726762}
727763
728764pub fn collapse_selection(cx: &mut Context) {
765+ let view_id = cx.view_id;
729766 let doc = cx.doc();
730767 let selection = doc
731− .selection()
768+ .selection(view_id)
732769 .transform(|range| Range::new(range.head, range.head));
733770
734− doc.set_selection(selection);
771+ doc.set_selection(view_id, selection);
735772}
736773
737774pub fn flip_selections(cx: &mut Context) {
775+ let view_id = cx.view_id;
738776 let doc = cx.doc();
739777 let selection = doc
740− .selection()
778+ .selection(view_id)
741779 .transform(|range| Range::new(range.head, range.anchor));
742780
743− doc.set_selection(selection);
781+ doc.set_selection(view_id, selection);
744782}
745783
746784fn enter_insert_mode(doc: &mut Document) {
@@ -749,29 +787,31 @@ fn enter_insert_mode(doc: &mut Document) {
749787
750788// inserts at the start of each selection
751789pub fn insert_mode(cx: &mut Context) {
790+ let view_id = cx.view_id;
752791 let doc = cx.doc();
753792 enter_insert_mode(doc);
754793
755794 let selection = doc
756− .selection()
795+ .selection(view_id)
757796 .transform(|range| Range::new(range.to(), range.from()));
758− doc.set_selection(selection);
797+ doc.set_selection(view_id, selection);
759798}
760799
761800// inserts at the end of each selection
762801pub fn append_mode(cx: &mut Context) {
802+ let view_id = cx.view_id;
763803 let doc = cx.doc();
764804 enter_insert_mode(doc);
765805 doc.restore_cursor = true;
766806
767807 let text = doc.text().slice(..);
768− let selection = doc.selection().transform(|range| {
808+ let selection = doc.selection(view_id).transform(|range| {
769809 Range::new(
770810 range.from(),
771811 graphemes::next_grapheme_boundary(text, range.to()), // to() + next char
772812 )
773813 });
774− doc.set_selection(selection);
814+ doc.set_selection(view_id, selection);
775815}
776816
777817const COMMAND_LIST: &[&str] = &["write", "open", "quit"];
@@ -931,25 +971,27 @@ pub fn prepend_to_line(cx: &mut Context) {
931971pub fn append_to_line(cx: &mut Context) {
932972 move_line_end(cx);
933973
974+ let view_id = cx.view_id;
934975 let doc = cx.doc();
935976 enter_insert_mode(doc);
936977
937978 // offset by another 1 char since move_line_end will position on the last char, we want to
938979 // append past that
939− let selection = doc.selection().transform(|range| {
980+ let selection = doc.selection(view_id).transform(|range| {
940981 let pos = range.head + 1;
941982 Range::new(pos, pos)
942983 });
943− doc.set_selection(selection);
984+ doc.set_selection(view_id, selection);
944985}
945986
946987// o inserts a new line after each line with a selection
947988pub fn open_below(cx: &mut Context) {
989+ let view_id = cx.view_id;
948990 let count = cx.count;
949991 let doc = cx.doc();
950992 enter_insert_mode(doc);
951993
952− let lines = selection_lines(doc.text(), doc.selection());
994+ let lines = selection_lines(doc.text(), doc.selection(view_id));
953995
954996 let positions = lines.into_iter().map(|index| {
955997 // adjust all positions to the end of the line (next line minus one)
@@ -991,16 +1033,17 @@ pub fn open_below(cx: &mut Context) {
9911033 let transaction =
9921034 Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
9931035
994− doc.apply(&transaction);
1036+ doc.apply(&transaction, view_id);
9951037}
9961038
9971039// O inserts a new line before each line with a selection
9981040pub fn open_above(cx: &mut Context) {
1041+ let view_id = cx.view_id;
9991042 let count = cx.count;
10001043 let doc = cx.doc();
10011044 enter_insert_mode(doc);
10021045
1003− let lines = selection_lines(doc.text(), doc.selection());
1046+ let lines = selection_lines(doc.text(), doc.selection(view_id));
10041047
10051048 let positions = lines.into_iter().map(|index| {
10061049 // adjust all positions to the end of the previous line
@@ -1043,26 +1086,27 @@ pub fn open_above(cx: &mut Context) {
10431086 let transaction =
10441087 Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
10451088
1046− doc.apply(&transaction);
1089+ doc.apply(&transaction, view_id);
10471090}
10481091
10491092pub fn normal_mode(cx: &mut Context) {
1093+ let view_id = cx.view_id;
10501094 let doc = cx.doc();
10511095
10521096 doc.mode = Mode::Normal;
10531097
1054− doc.append_changes_to_history();
1098+ doc.append_changes_to_history(view_id);
10551099
10561100 // if leaving append mode, move cursor back by 1
10571101 if doc.restore_cursor {
10581102 let text = doc.text().slice(..);
1059− let selection = doc.selection().transform(|range| {
1103+ let selection = doc.selection(view_id).transform(|range| {
10601104 Range::new(
10611105 range.from(),
10621106 graphemes::prev_grapheme_boundary(text, range.to()),
10631107 )
10641108 });
1065− doc.set_selection(selection);
1109+ doc.set_selection(view_id, selection);
10661110
10671111 doc.restore_cursor = false;
10681112 }
@@ -1071,13 +1115,15 @@ pub fn normal_mode(cx: &mut Context) {
10711115// Store a jump on the jumplist.
10721116fn push_jump(cx: &mut Context) {
10731117 let jump = {
1118+ let view_id = cx.view_id;
10741119 let doc = cx.doc();
1075− (doc.id(), doc.selection().clone())
1120+ (doc.id(), doc.selection(view_id).clone())
10761121 };
10771122 cx.view().jumps.push(jump);
10781123}
10791124
10801125pub fn goto_mode(cx: &mut Context) {
1126+ let view_id = cx.view_id;
10811127 let count = cx.count;
10821128
10831129 if count > 1 {
@@ -1087,7 +1133,7 @@ pub fn goto_mode(cx: &mut Context) {
10871133 // to 1g
10881134 let doc = cx.doc();
10891135 let pos = doc.text().line_to_char(count - 1);
1090− doc.set_selection(Selection::point(pos));
1136+ doc.set_selection(view_id, Selection::point(pos));
10911137 return;
10921138 }
10931139
@@ -1128,10 +1174,11 @@ fn _goto(cx: &mut Context, locations: Vec<lsp::Location>) {
11281174 let id = editor
11291175 .open(PathBuf::from(location.uri.path()), action)
11301176 .expect("editor.open failed");
1177+ let view_id = editor.view().id;
11311178 let doc = &mut editor.documents[id];
11321179 let definition_pos = location.range.start;
11331180 let new_pos = helix_lsp::util::lsp_pos_to_pos(doc.text(), definition_pos);
1134− doc.set_selection(Selection::point(new_pos));
1181+ doc.set_selection(view_id, Selection::point(new_pos));
11351182 }
11361183
11371184 match locations.as_slice() {
@@ -1155,6 +1202,7 @@ fn _goto(cx: &mut Context, locations: Vec<lsp::Location>) {
11551202}
11561203
11571204pub fn goto_definition(cx: &mut Context) {
1205+ let view_id = cx.view_id;
11581206 let doc = cx.doc();
11591207 let language_server = match doc.language_server() {
11601208 Some(language_server) => language_server,
@@ -1162,7 +1210,7 @@ pub fn goto_definition(cx: &mut Context) {
11621210 };
11631211
11641212 // TODO: blocking here is not ideal
1165− let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection().cursor());
1213+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view_id).cursor());
11661214
11671215 // TODO: handle fails
11681216 let res =
@@ -1171,6 +1219,7 @@ pub fn goto_definition(cx: &mut Context) {
11711219}
11721220
11731221pub fn goto_type_definition(cx: &mut Context) {
1222+ let view_id = cx.view_id;
11741223 let doc = cx.doc();
11751224 let language_server = match doc.language_server() {
11761225 Some(language_server) => language_server,
@@ -1178,7 +1227,7 @@ pub fn goto_type_definition(cx: &mut Context) {
11781227 };
11791228
11801229 // TODO: blocking here is not ideal
1181− let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection().cursor());
1230+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view_id).cursor());
11821231
11831232 // TODO: handle fails
11841233 let res = smol::block_on(language_server.goto_type_definition(doc.identifier(), pos))
@@ -1187,6 +1236,7 @@ pub fn goto_type_definition(cx: &mut Context) {
11871236}
11881237
11891238pub fn goto_implementation(cx: &mut Context) {
1239+ let view_id = cx.view_id;
11901240 let doc = cx.doc();
11911241 let language_server = match doc.language_server() {
11921242 Some(language_server) => language_server,
@@ -1194,7 +1244,7 @@ pub fn goto_implementation(cx: &mut Context) {
11941244 };
11951245
11961246 // TODO: blocking here is not ideal
1197− let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection().cursor());
1247+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view_id).cursor());
11981248
11991249 // TODO: handle fails
12001250 let res = smol::block_on(language_server.goto_implementation(doc.identifier(), pos))
@@ -1203,6 +1253,7 @@ pub fn goto_implementation(cx: &mut Context) {
12031253}
12041254
12051255pub fn goto_reference(cx: &mut Context) {
1256+ let view_id = cx.view_id;
12061257 let doc = cx.doc();
12071258 let language_server = match doc.language_server() {
12081259 Some(language_server) => language_server,
@@ -1210,7 +1261,7 @@ pub fn goto_reference(cx: &mut Context) {
12101261 };
12111262
12121263 // TODO: blocking here is not ideal
1213− let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection().cursor());
1264+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view_id).cursor());
12141265
12151266 // TODO: handle fails
12161267 let res =
@@ -1219,6 +1270,7 @@ pub fn goto_reference(cx: &mut Context) {
12191270}
12201271
12211272pub fn signature_help(cx: &mut Context) {
1273+ let view_id = cx.view_id;
12221274 let doc = cx.doc();
12231275
12241276 let language_server = match doc.language_server() {
@@ -1227,7 +1279,7 @@ pub fn signature_help(cx: &mut Context) {
12271279 };
12281280
12291281 // TODO: blocking here is not ideal
1230− let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection().cursor());
1282+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view_id).cursor());
12311283
12321284 // TODO: handle fails
12331285
@@ -1320,20 +1372,21 @@ pub mod insert {
13201372
13211373 // TODO: insert means add text just before cursor, on exit we should be on the last letter.
13221374 pub fn insert_char(cx: &mut Context, c: char) {
1375+ let view_id = cx.view_id;
13231376 let doc = cx.doc();
13241377
13251378 // run through insert hooks, stopping on the first one that returns Some(t)
13261379 for hook in HOOKS {
1327− if let Some(transaction) = hook(doc.text(), doc.selection(), c) {
1328− doc.apply(&transaction);
1380+ if let Some(transaction) = hook(doc.text(), doc.selection(view_id), c) {
1381+ doc.apply(&transaction, view_id);
13291382 return;
13301383 }
13311384 }
13321385
13331386 let t = Tendril::from_char(c);
1334− let transaction = Transaction::insert(doc.text(), doc.selection(), t);
1387+ let transaction = Transaction::insert(doc.text(), doc.selection(view_id), t);
13351388
1336− doc.apply(&transaction);
1389+ doc.apply(&transaction, view_id);
13371390
13381391 // TODO: need a post insert hook too for certain triggers (autocomplete, signature help, etc)
13391392 // this could also generically look at Transaction, but it's a bit annoying to look at
@@ -1344,58 +1397,69 @@ pub mod insert {
13441397 }
13451398
13461399 pub fn insert_tab(cx: &mut Context) {
1400+ let view_id = cx.view_id;
13471401 let doc = cx.doc();
13481402 // TODO: round out to nearest indentation level (for example a line with 3 spaces should
13491403 // indent by one to reach 4 spaces).
13501404
13511405 let indent = Tendril::from(doc.indent_unit());
1352− let transaction = Transaction::insert(doc.text(), doc.selection(), indent);
1353− doc.apply(&transaction);
1406+ let transaction = Transaction::insert(doc.text(), doc.selection(view_id), indent);
1407+ doc.apply(&transaction, view_id);
13541408 }
13551409
13561410 pub fn insert_newline(cx: &mut Context) {
1411+ let view_id = cx.view_id;
13571412 let doc = cx.doc();
13581413 let text = doc.text().slice(..);
1359− let transaction = Transaction::change_by_selection(doc.text(), doc.selection(), |range| {
1360− // TODO: offset range.head by 1? when calculating?
1361− let indent_level =
1362− helix_core::indent::suggested_indent_for_pos(doc.syntax(), text, range.head, true);
1363− let indent = doc.indent_unit().repeat(indent_level);
1364− let mut text = String::with_capacity(1 + indent.len());
1365− text.push('\n');
1366− text.push_str(&indent);
1367− (range.head, range.head, Some(text.into()))
1368− });
1369− doc.apply(&transaction);
1414+ let transaction =
1415+ Transaction::change_by_selection(doc.text(), doc.selection(view_id), |range| {
1416+ // TODO: offset range.head by 1? when calculating?
1417+ let indent_level = helix_core::indent::suggested_indent_for_pos(
1418+ doc.syntax(),
1419+ text,
1420+ range.head,
1421+ true,
1422+ );
1423+ let indent = doc.indent_unit().repeat(indent_level);
1424+ let mut text = String::with_capacity(1 + indent.len());
1425+ text.push('\n');
1426+ text.push_str(&indent);
1427+ (range.head, range.head, Some(text.into()))
1428+ });
1429+ doc.apply(&transaction, view_id);
13701430 }
13711431
13721432 // TODO: handle indent-aware delete
13731433 pub fn delete_char_backward(cx: &mut Context) {
1434+ let view_id = cx.view_id;
13741435 let count = cx.count;
13751436 let doc = cx.doc();
13761437 let text = doc.text().slice(..);
1377− let transaction = Transaction::change_by_selection(doc.text(), doc.selection(), |range| {
1378− (
1379− graphemes::nth_prev_grapheme_boundary(text, range.head, count),
1380− range.head,
1381− None,
1382− )
1383− });
1384− doc.apply(&transaction);
1438+ let transaction =
1439+ Transaction::change_by_selection(doc.text(), doc.selection(view_id), |range| {
1440+ (
1441+ graphemes::nth_prev_grapheme_boundary(text, range.head, count),
1442+ range.head,
1443+ None,
1444+ )
1445+ });
1446+ doc.apply(&transaction, view_id);
13851447 }
13861448
13871449 pub fn delete_char_forward(cx: &mut Context) {
1450+ let view_id = cx.view_id;
13881451 let count = cx.count;
13891452 let doc = cx.doc();
13901453 let text = doc.text().slice(..);
1391− let transaction = Transaction::change_by_selection(doc.text(), doc.selection(), |range| {
1392− (
1393− range.head,
1394− graphemes::nth_next_grapheme_boundary(text, range.head, count),
1395− None,
1396− )
1397− });
1398− doc.apply(&transaction);
1454+ let transaction =
1455+ Transaction::change_by_selection(doc.text(), doc.selection(view_id), |range| {
1456+ (
1457+ range.head,
1458+ graphemes::nth_next_grapheme_boundary(text, range.head, count),
1459+ None,
1460+ )
1461+ });
1462+ doc.apply(&transaction, view_id);
13991463 }
14001464}
14011465
@@ -1405,20 +1469,23 @@ pub mod insert {
14051469// storing it?
14061470
14071471pub fn undo(cx: &mut Context) {
1408− cx.doc().undo();
1472+ let view_id = cx.view_id;
1473+ cx.doc().undo(view_id);
14091474}
14101475
14111476pub fn redo(cx: &mut Context) {
1412− cx.doc().redo();
1477+ let view_id = cx.view_id;
1478+ cx.doc().redo(view_id);
14131479}
14141480
14151481// Yank / Paste
14161482
14171483pub fn yank(cx: &mut Context) {
14181484 // TODO: should selections be made end inclusive?
1485+ let view_id = cx.view_id;
14191486 let doc = cx.doc();
14201487 let values: Vec<String> = doc
1421− .selection()
1488+ .selection(view_id)
14221489 .fragments(doc.text().slice(..))
14231490 .map(|cow| cow.into_owned())
14241491 .collect();
@@ -1461,32 +1528,33 @@ pub fn paste(cx: &mut Context) {
14611528
14621529 let mut values = values.into_iter().map(Tendril::from).chain(repeat);
14631530
1531+ let view_id = cx.view_id;
14641532 let doc = cx.doc();
14651533
14661534 let transaction = if linewise {
14671535 // paste on the next line
14681536 // TODO: can simply take a range + modifier and compute the right pos without ifs
14691537 let text = doc.text();
1470− Transaction::change_by_selection(doc.text(), doc.selection(), |range| {
1538+ Transaction::change_by_selection(doc.text(), doc.selection(view_id), |range| {
14711539 let line_end = text.line_to_char(text.char_to_line(range.head) + 1);
14721540 (line_end, line_end, Some(values.next().unwrap()))
14731541 })
14741542 } else {
1475− Transaction::change_by_selection(doc.text(), doc.selection(), |range| {
1543+ Transaction::change_by_selection(doc.text(), doc.selection(view_id), |range| {
14761544 (range.head + 1, range.head + 1, Some(values.next().unwrap()))
14771545 })
14781546 };
14791547
1480− doc.apply(&transaction);
1481− doc.append_changes_to_history();
1548+ doc.apply(&transaction, view_id);
1549+ doc.append_changes_to_history(view_id);
14821550 }
14831551}
14841552
1485−fn get_lines(doc: &Document) -> Vec<usize> {
1553+fn get_lines(doc: &Document, view_id: ViewId) -> Vec<usize> {
14861554 let mut lines = Vec::new();
14871555
14881556 // Get all line numbers
1489− for range in doc.selection() {
1557+ for range in doc.selection(view_id) {
14901558 let start = doc.text().char_to_line(range.from());
14911559 let end = doc.text().char_to_line(range.to());
14921560
@@ -1500,8 +1568,9 @@ fn get_lines(doc: &Document) -> Vec<usize> {
15001568}
15011569
15021570pub fn indent(cx: &mut Context) {
1571+ let view_id = cx.view_id;
15031572 let doc = cx.doc();
1504− let lines = get_lines(doc);
1573+ let lines = get_lines(doc, view_id);
15051574
15061575 // Indent by one level
15071576 let indent = Tendril::from(doc.indent_unit());
@@ -1513,13 +1582,14 @@ pub fn indent(cx: &mut Context) {
15131582 (pos, pos, Some(indent.clone()))
15141583 }),
15151584 );
1516− doc.apply(&transaction);
1517− doc.append_changes_to_history();
1585+ doc.apply(&transaction, view_id);
1586+ doc.append_changes_to_history(view_id);
15181587}
15191588
15201589pub fn unindent(cx: &mut Context) {
1590+ let view_id = cx.view_id;
15211591 let doc = cx.doc();
1522− let lines = get_lines(doc);
1592+ let lines = get_lines(doc, view_id);
15231593 let mut changes = Vec::with_capacity(lines.len());
15241594 let tab_width = doc.tab_width();
15251595
@@ -1547,12 +1617,13 @@ pub fn unindent(cx: &mut Context) {
15471617
15481618 let transaction = Transaction::change(doc.text(), changes.into_iter());
15491619
1550− doc.apply(&transaction);
1551− doc.append_changes_to_history();
1620+ doc.apply(&transaction, view_id);
1621+ doc.append_changes_to_history(view_id);
15521622}
15531623
15541624pub fn format_selections(cx: &mut Context) {
15551625 use helix_lsp::lsp;
1626+ let view_id = cx.view_id;
15561627 let doc = cx.doc();
15571628
15581629 // via lsp if available
@@ -1561,7 +1632,7 @@ pub fn format_selections(cx: &mut Context) {
15611632 // TODO: blocking here is not ideal
15621633
15631634 let ranges: Vec<lsp::Range> = doc
1564− .selection()
1635+ .selection(view_id)
15651636 .iter()
15661637 .map(|range| helix_lsp::util::range_to_lsp_range(doc.text(), *range))
15671638 .collect();
@@ -1583,14 +1654,15 @@ pub fn format_selections(cx: &mut Context) {
15831654
15841655 let transaction = helix_lsp::util::generate_transaction_from_edits(doc.text(), edits);
15851656
1586− doc.apply(&transaction);
1657+ doc.apply(&transaction, view_id);
15871658 }
15881659
1589− doc.append_changes_to_history();
1660+ doc.append_changes_to_history(view_id);
15901661}
15911662
15921663pub fn join_selections(cx: &mut Context) {
15931664 use movement::skip_over_next;
1665+ let view_id = cx.view_id;
15941666 let doc = cx.doc();
15951667 let text = doc.text();
15961668 let slice = doc.text().slice(..);
@@ -1598,7 +1670,7 @@ pub fn join_selections(cx: &mut Context) {
15981670 let mut changes = Vec::new();
15991671 let fragment = Tendril::from(" ");
16001672
1601− for selection in doc.selection() {
1673+ for selection in doc.selection(view_id) {
16021674 let start = text.char_to_line(selection.from());
16031675 let mut end = text.char_to_line(selection.to());
16041676 if start == end {
@@ -1629,17 +1701,18 @@ pub fn join_selections(cx: &mut Context) {
16291701 // TODO: select inserted spaces
16301702 // .with_selection(selection);
16311703
1632− doc.apply(&transaction);
1633− doc.append_changes_to_history();
1704+ doc.apply(&transaction, view_id);
1705+ doc.append_changes_to_history(view_id);
16341706}
16351707
16361708pub fn keep_selections(cx: &mut Context) {
16371709 // keep selections matching regex
1638− let prompt = ui::regex_prompt(cx, "keep:".to_string(), |doc, regex| {
1710+ let view_id = cx.view_id;
1711+ let prompt = ui::regex_prompt(cx, "keep:".to_string(), move |doc, regex| {
16391712 let text = doc.text().slice(..);
16401713
1641− if let Some(selection) = selection::keep_matches(text, doc.selection(), ®ex) {
1642− doc.set_selection(selection);
1714+ if let Some(selection) = selection::keep_matches(text, doc.selection(view_id), ®ex) {
1715+ doc.set_selection(view_id, selection);
16431716 }
16441717 });
16451718
@@ -1647,11 +1720,12 @@ pub fn keep_selections(cx: &mut Context) {
16471720}
16481721
16491722pub fn keep_primary_selection(cx: &mut Context) {
1723+ let view_id = cx.view_id;
16501724 let doc = cx.doc();
16511725
1652− let range = doc.selection().primary();
1726+ let range = doc.selection(view_id).primary();
16531727 let selection = Selection::single(range.anchor, range.head);
1654− doc.set_selection(selection);
1728+ doc.set_selection(view_id, selection);
16551729}
16561730
16571731//
@@ -1700,6 +1774,7 @@ pub fn completion(cx: &mut Context) {
17001774 // The prefix still has to satisfy `company-minimum-prefix-length' before that
17011775 // happens. The value of nil means no idle completion."
17021776
1777+ let view_id = cx.view_id;
17031778 let doc = cx.doc();
17041779
17051780 let language_server = match doc.language_server() {
@@ -1708,13 +1783,13 @@ pub fn completion(cx: &mut Context) {
17081783 };
17091784
17101785 // TODO: blocking here is not ideal
1711− let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection().cursor());
1786+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view_id).cursor());
17121787
17131788 // TODO: handle fails
17141789
17151790 let res = smol::block_on(language_server.completion(doc.identifier(), pos)).unwrap();
17161791
1717− let trigger_offset = doc.selection().cursor();
1792+ let trigger_offset = doc.selection(view_id).cursor();
17181793
17191794 cx.callback(
17201795 res,
@@ -1751,6 +1826,7 @@ pub fn completion(cx: &mut Context) {
17511826pub fn hover(cx: &mut Context) {
17521827 use helix_lsp::lsp;
17531828
1829+ let view_id = cx.view_id;
17541830 let doc = cx.doc();
17551831
17561832 let language_server = match doc.language_server() {
@@ -1762,7 +1838,7 @@ pub fn hover(cx: &mut Context) {
17621838
17631839 // TODO: blocking here is not ideal, make commands async fn?
17641840 // not like we can process additional input meanwhile though
1765− let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection().cursor());
1841+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text(), doc.selection(view_id).cursor());
17661842
17671843 // TODO: handle fails
17681844 let res = smol::block_on(language_server.text_document_hover(doc.identifier(), pos))
@@ -1798,33 +1874,36 @@ pub fn next_view(cx: &mut Context) {
17981874
17991875// comments
18001876pub fn toggle_comments(cx: &mut Context) {
1877+ let view_id = cx.view_id;
18011878 let doc = cx.doc();
1802− let transaction = comment::toggle_line_comments(doc.text(), doc.selection());
1879+ let transaction = comment::toggle_line_comments(doc.text(), doc.selection(view_id));
18031880
1804− doc.apply(&transaction);
1805− doc.append_changes_to_history();
1881+ doc.apply(&transaction, view_id);
1882+ doc.append_changes_to_history(view_id);
18061883}
18071884
18081885// tree sitter node selection
18091886
18101887pub fn expand_selection(cx: &mut Context) {
1888+ let view_id = cx.view_id;
18111889 let doc = cx.doc();
18121890
18131891 if let Some(syntax) = doc.syntax() {
18141892 let text = doc.text().slice(..);
1815− let selection = object::expand_selection(syntax, text, doc.selection());
1816− doc.set_selection(selection);
1893+ let selection = object::expand_selection(syntax, text, doc.selection(view_id));
1894+ doc.set_selection(view_id, selection);
18171895 }
18181896}
18191897
18201898pub fn match_brackets(cx: &mut Context) {
1899+ let view_id = cx.view_id;
18211900 let doc = cx.doc();
18221901
18231902 if let Some(syntax) = doc.syntax() {
1824− let pos = doc.selection().cursor();
1903+ let pos = doc.selection(view_id).cursor();
18251904 if let Some(pos) = match_brackets::find(syntax, doc.text(), pos) {
18261905 let selection = Selection::point(pos);
1827− doc.set_selection(selection);
1906+ doc.set_selection(view_id, selection);
18281907 };
18291908 }
18301909}
@@ -1836,6 +1915,7 @@ pub fn jump_forward(cx: &mut Context) {
18361915 let view = cx.view();
18371916
18381917 if let Some((id, selection)) = view.jumps.forward(count) {
1918+ // TODO: position first_line so that main cursor is centered
18391919 view.first_line = 0;
18401920 view.doc = *id;
18411921 };
@@ -1846,11 +1926,13 @@ pub fn jump_backward(cx: &mut Context) {
18461926 let view = cx.view();
18471927
18481928 if let Some((id, selection)) = view.jumps.backward(count) {
1929+ // TODO: position first_line so that main cursor is centered
18491930 view.first_line = 0;
18501931 view.doc = *id;
18511932 let selection = selection.clone();
1933+ let view_id = view.id;
18521934 let doc = cx.doc();
1853− doc.set_selection(selection);
1935+ doc.set_selection(view_id, selection);
18541936 };
18551937}
18561938