on master help sign in
Simplify code by providin cx.current() = (view, doc).
0dbd5b6Blaž Hrastnik
@@ -23,6 +23,8 @@
23- [ ] repeat insert/command -> transaction
23- [ ] repeat insert/command -> transaction
24- [ ] repeat selection
24- [ ] repeat selection
25
25
26+- [] jump to alt buffer
27+
26- [ ] load toml configs, themes, tabsize/identation
28- [ ] load toml configs, themes, tabsize/identation
27
29
28- [ ] draw separator line between views
30- [ ] draw separator line between views
helix-term/src/commands.rs+186−255
@@ -55,6 +55,11 @@ impl<'a> Context<'a> {
55 &mut self.editor.documents[id]
55 &mut self.editor.documents[id]
56 }
56 }
57
57
58+ #[inline]
59+ pub fn current(&mut self) -> (&mut View, &mut Document) {
60+ self.editor.current()
61+ }
62+
58 /// Push a new component onto the compositor.
63 /// Push a new component onto the compositor.
59 pub fn push_layer(&mut self, mut component: Box<dyn Component>) {
64 pub fn push_layer(&mut self, mut component: Box<dyn Component>) {
60 self.callback = Some(Box::new(
65 self.callback = Some(Box::new(
@@ -103,10 +108,9 @@ pub type Command = fn(cx: &mut Context);
103
108
104pub fn move_char_left(cx: &mut Context) {
109pub fn move_char_left(cx: &mut Context) {
105 let count = cx.count;
110 let count = cx.count;
106− let view_id = cx.view_id;
111+ let (view, doc) = cx.current();
107− let doc = cx.doc();
108 let text = doc.text().slice(..);
112 let text = doc.text().slice(..);
109− let selection = doc.selection(view_id).transform(|range| {
113+ let selection = doc.selection(view.id).transform(|range| {
110 movement::move_horizontally(
114 movement::move_horizontally(
111 text,
115 text,
112 range,
116 range,
@@ -115,15 +119,14 @@ pub fn move_char_left(cx: &mut Context) {
115 false, /* extend */
119 false, /* extend */
116 )
120 )
117 });
121 });
118− doc.set_selection(view_id, selection);
122+ doc.set_selection(view.id, selection);
119}
123}
120
124
121pub fn move_char_right(cx: &mut Context) {
125pub fn move_char_right(cx: &mut Context) {
122 let count = cx.count;
126 let count = cx.count;
123− let view_id = cx.view_id;
127+ let (view, doc) = cx.current();
124− let doc = cx.doc();
125 let text = doc.text().slice(..);
128 let text = doc.text().slice(..);
126− let selection = doc.selection(view_id).transform(|range| {
129+ let selection = doc.selection(view.id).transform(|range| {
127 movement::move_horizontally(
130 movement::move_horizontally(
128 text,
131 text,
129 range,
132 range,
@@ -132,15 +135,14 @@ pub fn move_char_right(cx: &mut Context) {
132 false, /* extend */
135 false, /* extend */
133 )
136 )
134 });
137 });
135− doc.set_selection(view_id, selection);
138+ doc.set_selection(view.id, selection);
136}
139}
137
140
138pub fn move_line_up(cx: &mut Context) {
141pub fn move_line_up(cx: &mut Context) {
139 let count = cx.count;
142 let count = cx.count;
140− let view_id = cx.view_id;
143+ let (view, doc) = cx.current();
141− let doc = cx.doc();
142 let text = doc.text().slice(..);
144 let text = doc.text().slice(..);
143− let selection = doc.selection(view_id).transform(|range| {
145+ let selection = doc.selection(view.id).transform(|range| {
144 movement::move_vertically(
146 movement::move_vertically(
145 text,
147 text,
146 range,
148 range,
@@ -149,15 +151,14 @@ pub fn move_line_up(cx: &mut Context) {
149 false, /* extend */
151 false, /* extend */
150 )
152 )
151 });
153 });
152− doc.set_selection(view_id, selection);
154+ doc.set_selection(view.id, selection);
153}
155}
154
156
155pub fn move_line_down(cx: &mut Context) {
157pub fn move_line_down(cx: &mut Context) {
156 let count = cx.count;
158 let count = cx.count;
157− let view_id = cx.view_id;
159+ let (view, doc) = cx.current();
158− let doc = cx.doc();
159 let text = doc.text().slice(..);
160 let text = doc.text().slice(..);
160− let selection = doc.selection(view_id).transform(|range| {
161+ let selection = doc.selection(view.id).transform(|range| {
161 movement::move_vertically(
162 movement::move_vertically(
162 text,
163 text,
163 range,
164 range,
@@ -166,13 +167,12 @@ pub fn move_line_down(cx: &mut Context) {
166 false, /* extend */
167 false, /* extend */
167 )
168 )
168 });
169 });
169− doc.set_selection(view_id, selection);
170+ doc.set_selection(view.id, selection);
170}
171}
171
172
172pub fn move_line_end(cx: &mut Context) {
173pub fn move_line_end(cx: &mut Context) {
173− let view_id = cx.view_id;
174+ let (view, doc) = cx.current();
174− let doc = cx.doc();
175− let lines = selection_lines(doc.text(), doc.selection(view_id));
175+ let lines = selection_lines(doc.text(), doc.selection(view.id));
176
176
177 let positions = lines
177 let positions = lines
178 .into_iter()
178 .into_iter()
@@ -187,13 +187,12 @@ pub fn move_line_end(cx: &mut Context) {
187
187
188 let selection = Selection::new(positions.collect(), 0);
188 let selection = Selection::new(positions.collect(), 0);
189
189
190− doc.set_selection(view_id, selection);
190+ doc.set_selection(view.id, selection);
191}
191}
192
192
193pub fn move_line_start(cx: &mut Context) {
193pub fn move_line_start(cx: &mut Context) {
194− let view_id = cx.view_id;
194+ let (view, doc) = cx.current();
195− let doc = cx.doc();
196− let lines = selection_lines(doc.text(), doc.selection(view_id));
195+ let lines = selection_lines(doc.text(), doc.selection(view.id));
197
196
198 let positions = lines
197 let positions = lines
199 .into_iter()
198 .into_iter()
@@ -205,7 +204,7 @@ pub fn move_line_start(cx: &mut Context) {
205
204
206 let selection = Selection::new(positions.collect(), 0);
205 let selection = Selection::new(positions.collect(), 0);
207
206
208− doc.set_selection(view_id, selection);
207+ doc.set_selection(view.id, selection);
209}
208}
210
209
211// TODO: move vs extend could take an extra type Extend/Move that would
210// 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) {
214
213
215pub fn move_next_word_start(cx: &mut Context) {
214pub fn move_next_word_start(cx: &mut Context) {
216 let count = cx.count;
215 let count = cx.count;
217− let view_id = cx.view_id;
216+ let (view, doc) = cx.current();
218− let doc = cx.doc();
219 let text = doc.text().slice(..);
217 let text = doc.text().slice(..);
220
218
221− let selection = doc.selection(view_id).transform(|range| {
219+ let selection = doc.selection(view.id).transform(|range| {
222 let pos = movement::move_next_word_start(text, range.head, count);
220 let pos = movement::move_next_word_start(text, range.head, count);
223 Range::new(pos, pos)
221 Range::new(pos, pos)
224 });
222 });
225
223
226− doc.set_selection(view_id, selection);
224+ doc.set_selection(view.id, selection);
227}
225}
228
226
229pub fn move_prev_word_start(cx: &mut Context) {
227pub fn move_prev_word_start(cx: &mut Context) {
230 let count = cx.count;
228 let count = cx.count;
231− let view_id = cx.view_id;
229+ let (view, doc) = cx.current();
232− let doc = cx.doc();
233 let text = doc.text().slice(..);
230 let text = doc.text().slice(..);
234
231
235− let selection = doc.selection(view_id).transform(|range| {
232+ let selection = doc.selection(view.id).transform(|range| {
236 let pos = movement::move_prev_word_start(text, range.head, count);
233 let pos = movement::move_prev_word_start(text, range.head, count);
237 Range::new(pos, pos)
234 Range::new(pos, pos)
238 });
235 });
239
236
240− doc.set_selection(view_id, selection);
237+ doc.set_selection(view.id, selection);
241}
238}
242
239
243pub fn move_next_word_end(cx: &mut Context) {
240pub fn move_next_word_end(cx: &mut Context) {
244 let count = cx.count;
241 let count = cx.count;
245− let view_id = cx.view_id;
242+ let (view, doc) = cx.current();
246− let doc = cx.doc();
247 let text = doc.text().slice(..);
243 let text = doc.text().slice(..);
248
244
249− let selection = doc.selection(view_id).transform(|range| {
245+ let selection = doc.selection(view.id).transform(|range| {
250 let pos = movement::move_next_word_end(text, range.head, count);
246 let pos = movement::move_next_word_end(text, range.head, count);
251 Range::new(pos, pos)
247 Range::new(pos, pos)
252 });
248 });
253
249
254− doc.set_selection(view_id, selection);
250+ doc.set_selection(view.id, selection);
255}
251}
256
252
257pub fn move_file_start(cx: &mut Context) {
253pub fn move_file_start(cx: &mut Context) {
258 push_jump(cx);
254 push_jump(cx);
259− let view_id = cx.view_id;
255+ let (view, doc) = cx.current();
260− let doc = cx.doc();
261− doc.set_selection(view_id, Selection::point(0));
256+ doc.set_selection(view.id, Selection::point(0));
262}
257}
263
258
264pub fn move_file_end(cx: &mut Context) {
259pub fn move_file_end(cx: &mut Context) {
265 push_jump(cx);
260 push_jump(cx);
266− let view_id = cx.view_id;
261+ let (view, doc) = cx.current();
267− let doc = cx.doc();
268 let text = doc.text();
262 let text = doc.text();
269 let last_line = text.line_to_char(text.len_lines().saturating_sub(2));
263 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));
271}
265}
272
266
273pub fn extend_next_word_start(cx: &mut Context) {
267pub fn extend_next_word_start(cx: &mut Context) {
274 let count = cx.count;
268 let count = cx.count;
275− let view_id = cx.view_id;
269+ let (view, doc) = cx.current();
276− let doc = cx.doc();
277 let text = doc.text().slice(..);
270 let text = doc.text().slice(..);
278
271
279− let selection = doc.selection(view_id).transform(|mut range| {
272+ let selection = doc.selection(view.id).transform(|mut range| {
280 let pos = movement::move_next_word_start(text, range.head, count);
273 let pos = movement::move_next_word_start(text, range.head, count);
281 Range::new(range.anchor, pos)
274 Range::new(range.anchor, pos)
282 });
275 });
283
276
284− doc.set_selection(view_id, selection);
277+ doc.set_selection(view.id, selection);
285}
278}
286
279
287pub fn extend_prev_word_start(cx: &mut Context) {
280pub fn extend_prev_word_start(cx: &mut Context) {
288 let count = cx.count;
281 let count = cx.count;
289− let view_id = cx.view_id;
282+ let (view, doc) = cx.current();
290− let doc = cx.doc();
291 let text = doc.text().slice(..);
283 let text = doc.text().slice(..);
292
284
293− let selection = doc.selection(view_id).transform(|mut range| {
285+ let selection = doc.selection(view.id).transform(|mut range| {
294 let pos = movement::move_prev_word_start(text, range.head, count);
286 let pos = movement::move_prev_word_start(text, range.head, count);
295 Range::new(range.anchor, pos)
287 Range::new(range.anchor, pos)
296 });
288 });
297− doc.set_selection(view_id, selection);
289+ doc.set_selection(view.id, selection);
298}
290}
299
291
300pub fn extend_next_word_end(cx: &mut Context) {
292pub fn extend_next_word_end(cx: &mut Context) {
301 let count = cx.count;
293 let count = cx.count;
302− let view_id = cx.view_id;
294+ let (view, doc) = cx.current();
303− let doc = cx.doc();
304 let text = doc.text().slice(..);
295 let text = doc.text().slice(..);
305
296
306− let selection = doc.selection(view_id).transform(|mut range| {
297+ let selection = doc.selection(view.id).transform(|mut range| {
307 let pos = movement::move_next_word_end(text, range.head, count);
298 let pos = movement::move_next_word_end(text, range.head, count);
308 Range::new(range.anchor, pos)
299 Range::new(range.anchor, pos)
309 });
300 });
310
301
311− doc.set_selection(view_id, selection);
302+ doc.set_selection(view.id, selection);
312}
303}
313
304
314#[inline]
305#[inline]
@@ -329,11 +320,10 @@ where
329 ..
320 ..
330 } = event
321 } = event
331 {
322 {
332− let view_id = cx.view_id;
323+ let (view, doc) = cx.current();
333− let doc = cx.doc();
334 let text = doc.text().slice(..);
324 let text = doc.text().slice(..);
335
325
336− let selection = doc.selection(view_id).transform(|mut range| {
326+ let selection = doc.selection(view.id).transform(|mut range| {
337 search::find_nth_next(text, ch, range.head, count, inclusive).map_or(range, |pos| {
327 search::find_nth_next(text, ch, range.head, count, inclusive).map_or(range, |pos| {
338 if extend {
328 if extend {
339 Range::new(range.anchor, pos)
329 Range::new(range.anchor, pos)
@@ -345,7 +335,7 @@ where
345 })
335 })
346 });
336 });
347
337
348− doc.set_selection(view_id, selection);
338+ doc.set_selection(view.id, selection);
349 }
339 }
350 })
340 })
351}
341}
@@ -432,24 +422,22 @@ pub fn replace(cx: &mut Context) {
432 {
422 {
433 let text = Tendril::from_char(ch);
423 let text = Tendril::from_char(ch);
434
424
435− let view_id = cx.view_id;
425+ let (view, doc) = cx.current();
436− let doc = cx.doc();
437
426
438 let transaction =
427 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| {
440 (range.from(), range.to() + 1, Some(text.clone()))
429 (range.from(), range.to() + 1, Some(text.clone()))
441 });
430 });
442
431
443− doc.apply(&transaction, view_id);
432+ doc.apply(&transaction, view.id);
444− doc.append_changes_to_history(view_id);
433+ doc.append_changes_to_history(view.id);
445 }
434 }
446 })
435 })
447}
436}
448
437
449fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
438fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
450 use Direction::*;
439 use Direction::*;
451− let view = cx.editor.view();
440+ let (view, doc) = cx.current();
452− let doc = cx.editor.document(view.doc).unwrap();
453 let cursor = coords_at_pos(doc.text().slice(..), doc.selection(view.id).cursor());
441 let cursor = coords_at_pos(doc.text().slice(..), doc.selection(view.id).cursor());
454 let doc_last_line = doc.text().len_lines() - 1;
442 let doc_last_line = doc.text().len_lines() - 1;
455
443
@@ -466,9 +454,6 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
466 // cursor visual offset
454 // cursor visual offset
467 let cursor_off = cursor.row - view.first_line;
455 let cursor_off = cursor.row - view.first_line;
468
456
469− // upgrade to mut reference
470− let view = cx.editor.view_mut();
471−
472 view.first_line = match direction {
457 view.first_line = match direction {
473 Forward => view.first_line + offset,
458 Forward => view.first_line + offset,
474 Backward => view.first_line.saturating_sub(offset),
459 Backward => view.first_line.saturating_sub(offset),
@@ -481,17 +466,10 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
481 last_line.saturating_sub(scrolloff),
466 last_line.saturating_sub(scrolloff),
482 );
467 );
483
468
484− let view_id = view.id;
485−
486− // view drops here
487−
488− // upgrade to mut reference
489− let doc = cx.doc();
490−
491 let text = doc.text().slice(..);
469 let text = doc.text().slice(..);
492 let pos = pos_at_coords(text, Position::new(line, cursor.col)); // this func will properly truncate to line end
470 let pos = pos_at_coords(text, Position::new(line, cursor.col)); // this func will properly truncate to line end
493
471
494− doc.set_selection(view_id, Selection::point(pos));
472+ doc.set_selection(view.id, Selection::point(pos));
495}
473}
496
474
497pub fn page_up(cx: &mut Context) {
475pub fn page_up(cx: &mut Context) {
@@ -520,10 +498,9 @@ pub fn half_page_down(cx: &mut Context) {
520
498
521pub fn extend_char_left(cx: &mut Context) {
499pub fn extend_char_left(cx: &mut Context) {
522 let count = cx.count;
500 let count = cx.count;
523− let view_id = cx.view_id;
501+ let (view, doc) = cx.current();
524− let doc = cx.doc();
525 let text = doc.text().slice(..);
502 let text = doc.text().slice(..);
526− let selection = doc.selection(view_id).transform(|range| {
503+ let selection = doc.selection(view.id).transform(|range| {
527 movement::move_horizontally(
504 movement::move_horizontally(
528 text,
505 text,
529 range,
506 range,
@@ -532,15 +509,14 @@ pub fn extend_char_left(cx: &mut Context) {
532 true, /* extend */
509 true, /* extend */
533 )
510 )
534 });
511 });
535− doc.set_selection(view_id, selection);
512+ doc.set_selection(view.id, selection);
536}
513}
537
514
538pub fn extend_char_right(cx: &mut Context) {
515pub fn extend_char_right(cx: &mut Context) {
539 let count = cx.count;
516 let count = cx.count;
540− let view_id = cx.view_id;
517+ let (view, doc) = cx.current();
541− let doc = cx.doc();
542 let text = doc.text().slice(..);
518 let text = doc.text().slice(..);
543− let selection = doc.selection(view_id).transform(|range| {
519+ let selection = doc.selection(view.id).transform(|range| {
544 movement::move_horizontally(
520 movement::move_horizontally(
545 text,
521 text,
546 range,
522 range,
@@ -549,15 +525,14 @@ pub fn extend_char_right(cx: &mut Context) {
549 true, /* extend */
525 true, /* extend */
550 )
526 )
551 });
527 });
552− doc.set_selection(view_id, selection);
528+ doc.set_selection(view.id, selection);
553}
529}
554
530
555pub fn extend_line_up(cx: &mut Context) {
531pub fn extend_line_up(cx: &mut Context) {
556 let count = cx.count;
532 let count = cx.count;
557− let view_id = cx.view_id;
533+ let (view, doc) = cx.current();
558− let doc = cx.doc();
559 let text = doc.text().slice(..);
534 let text = doc.text().slice(..);
560− let selection = doc.selection(view_id).transform(|range| {
535+ let selection = doc.selection(view.id).transform(|range| {
561 movement::move_vertically(
536 movement::move_vertically(
562 text,
537 text,
563 range,
538 range,
@@ -566,15 +541,14 @@ pub fn extend_line_up(cx: &mut Context) {
566 true, /* extend */
541 true, /* extend */
567 )
542 )
568 });
543 });
569− doc.set_selection(view_id, selection);
544+ doc.set_selection(view.id, selection);
570}
545}
571
546
572pub fn extend_line_down(cx: &mut Context) {
547pub fn extend_line_down(cx: &mut Context) {
573 let count = cx.count;
548 let count = cx.count;
574− let view_id = cx.view_id;
549+ let (view, doc) = cx.current();
575− let doc = cx.doc();
576 let text = doc.text().slice(..);
550 let text = doc.text().slice(..);
577− let selection = doc.selection(view_id).transform(|range| {
551+ let selection = doc.selection(view.id).transform(|range| {
578 movement::move_vertically(
552 movement::move_vertically(
579 text,
553 text,
580 range,
554 range,
@@ -583,15 +557,14 @@ pub fn extend_line_down(cx: &mut Context) {
583 true, /* extend */
557 true, /* extend */
584 )
558 )
585 });
559 });
586− doc.set_selection(view_id, selection);
560+ doc.set_selection(view.id, selection);
587}
561}
588
562
589pub fn select_all(cx: &mut Context) {
563pub fn select_all(cx: &mut Context) {
590− let view_id = cx.view_id;
564+ let (view, doc) = cx.current();
591− let doc = cx.doc();
592
565
593 let end = doc.text().len_chars().saturating_sub(1);
566 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))
595}
568}
596
569
597pub fn select_regex(cx: &mut Context) {
570pub fn select_regex(cx: &mut Context) {
@@ -619,14 +592,13 @@ pub fn split_selection(cx: &mut Context) {
619}
592}
620
593
621pub fn split_selection_on_newline(cx: &mut Context) {
594pub fn split_selection_on_newline(cx: &mut Context) {
622− let view_id = cx.view_id;
595+ let (view, doc) = cx.current();
623− let doc = cx.doc();
624 let text = doc.text().slice(..);
596 let text = doc.text().slice(..);
625 // only compile the regex once
597 // only compile the regex once
626 #[allow(clippy::trivial_regex)]
598 #[allow(clippy::trivial_regex)]
627 static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\n").unwrap());
599 static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\n").unwrap());
628− let selection = selection::split_on_matches(text, doc.selection(view_id), &REGEX);
600+ let selection = selection::split_on_matches(text, doc.selection(view.id), &REGEX);
629− doc.set_selection(view_id, selection);
601+ doc.set_selection(view.id, selection);
630}
602}
631
603
632// search: searches for the first occurence in file, provides a prompt
604// search: searches for the first occurence in file, provides a prompt
@@ -685,10 +657,9 @@ pub fn search_next(cx: &mut Context) {
685}
657}
686
658
687pub fn search_selection(cx: &mut Context) {
659pub fn search_selection(cx: &mut Context) {
688− let view_id = cx.view_id;
660+ let (view, doc) = cx.current();
689− let doc = cx.doc();
690 let contents = doc.text().slice(..);
661 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);
692 let regex = regex::escape(&query);
663 let regex = regex::escape(&query);
693 register::set('\\', vec![regex]);
664 register::set('\\', vec![regex]);
694 search_next(cx);
665 search_next(cx);
@@ -702,24 +673,22 @@ pub fn search_selection(cx: &mut Context) {
702
673
703pub fn select_line(cx: &mut Context) {
674pub fn select_line(cx: &mut Context) {
704 let count = cx.count;
675 let count = cx.count;
705− let view_id = cx.view_id;
676+ let (view, doc) = cx.current();
706− let doc = cx.doc();
707
677
708− let pos = doc.selection(view_id).primary();
678+ let pos = doc.selection(view.id).primary();
709 let text = doc.text();
679 let text = doc.text();
710
680
711 let line = text.char_to_line(pos.head);
681 let line = text.char_to_line(pos.head);
712 let start = text.line_to_char(line);
682 let start = text.line_to_char(line);
713 let end = text.line_to_char(line + count).saturating_sub(1);
683 let end = text.line_to_char(line + count).saturating_sub(1);
714
684
715− doc.set_selection(view_id, Selection::single(start, end));
685+ doc.set_selection(view.id, Selection::single(start, end));
716}
686}
717pub fn extend_line(cx: &mut Context) {
687pub fn extend_line(cx: &mut Context) {
718− let view_id = cx.view_id;
719 let count = cx.count;
688 let count = cx.count;
720− let doc = cx.doc();
689+ let (view, doc) = cx.current();
721
690
722− let pos = doc.selection(view_id).primary();
691+ let pos = doc.selection(view.id).primary();
723 let text = doc.text();
692 let text = doc.text();
724
693
725 let line_start = text.char_to_line(pos.anchor);
694 let line_start = text.char_to_line(pos.anchor);
@@ -732,7 +701,7 @@ pub fn extend_line(cx: &mut Context) {
732 let start = text.line_to_char(line_start);
701 let start = text.line_to_char(line_start);
733 let end = text.line_to_char(line + 1).saturating_sub(1);
702 let end = text.line_to_char(line + 1).saturating_sub(1);
734
703
735− doc.set_selection(view_id, Selection::single(start, end));
704+ doc.set_selection(view.id, Selection::single(start, end));
736}
705}
737
706
738// heuristic: append changes to history after each command, unless we're in insert mode
707// 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) {
746}
715}
747
716
748pub fn delete_selection(cx: &mut Context) {
717pub fn delete_selection(cx: &mut Context) {
749− let view_id = cx.view_id;
718+ let (view, doc) = cx.current();
750− let doc = cx.doc();
751− _delete_selection(doc, view_id);
719+ _delete_selection(doc, view.id);
752
720
753− doc.append_changes_to_history(view_id);
721+ doc.append_changes_to_history(view.id);
754}
722}
755
723
756pub fn change_selection(cx: &mut Context) {
724pub fn change_selection(cx: &mut Context) {
757− let view_id = cx.view_id;
725+ let (view, doc) = cx.current();
758− let doc = cx.doc();
759− _delete_selection(doc, view_id);
726+ _delete_selection(doc, view.id);
760 enter_insert_mode(doc);
727 enter_insert_mode(doc);
761}
728}
762
729
763pub fn collapse_selection(cx: &mut Context) {
730pub fn collapse_selection(cx: &mut Context) {
764− let view_id = cx.view_id;
731+ let (view, doc) = cx.current();
765− let doc = cx.doc();
766 let selection = doc
732 let selection = doc
767− .selection(view_id)
733+ .selection(view.id)
768 .transform(|range| Range::new(range.head, range.head));
734 .transform(|range| Range::new(range.head, range.head));
769
735
770− doc.set_selection(view_id, selection);
736+ doc.set_selection(view.id, selection);
771}
737}
772
738
773pub fn flip_selections(cx: &mut Context) {
739pub fn flip_selections(cx: &mut Context) {
774− let view_id = cx.view_id;
740+ let (view, doc) = cx.current();
775− let doc = cx.doc();
776 let selection = doc
741 let selection = doc
777− .selection(view_id)
742+ .selection(view.id)
778 .transform(|range| Range::new(range.head, range.anchor));
743 .transform(|range| Range::new(range.head, range.anchor));
779
744
780− doc.set_selection(view_id, selection);
745+ doc.set_selection(view.id, selection);
781}
746}
782
747
783fn enter_insert_mode(doc: &mut Document) {
748fn enter_insert_mode(doc: &mut Document) {
@@ -786,31 +751,29 @@ fn enter_insert_mode(doc: &mut Document) {
786
751
787// inserts at the start of each selection
752// inserts at the start of each selection
788pub fn insert_mode(cx: &mut Context) {
753pub fn insert_mode(cx: &mut Context) {
789− let view_id = cx.view_id;
754+ let (view, doc) = cx.current();
790− let doc = cx.doc();
791 enter_insert_mode(doc);
755 enter_insert_mode(doc);
792
756
793 let selection = doc
757 let selection = doc
794− .selection(view_id)
758+ .selection(view.id)
795 .transform(|range| Range::new(range.to(), range.from()));
759 .transform(|range| Range::new(range.to(), range.from()));
796− doc.set_selection(view_id, selection);
760+ doc.set_selection(view.id, selection);
797}
761}
798
762
799// inserts at the end of each selection
763// inserts at the end of each selection
800pub fn append_mode(cx: &mut Context) {
764pub fn append_mode(cx: &mut Context) {
801− let view_id = cx.view_id;
765+ let (view, doc) = cx.current();
802− let doc = cx.doc();
803 enter_insert_mode(doc);
766 enter_insert_mode(doc);
804 doc.restore_cursor = true;
767 doc.restore_cursor = true;
805
768
806 let text = doc.text().slice(..);
769 let text = doc.text().slice(..);
807− let selection = doc.selection(view_id).transform(|range| {
770+ let selection = doc.selection(view.id).transform(|range| {
808 Range::new(
771 Range::new(
809 range.from(),
772 range.from(),
810 graphemes::next_grapheme_boundary(text, range.to()), // to() + next char
773 graphemes::next_grapheme_boundary(text, range.to()), // to() + next char
811 )
774 )
812 });
775 });
813− doc.set_selection(view_id, selection);
776+ doc.set_selection(view.id, selection);
814}
777}
815
778
816const COMMAND_LIST: &[&str] = &["write", "open", "quit"];
779const COMMAND_LIST: &[&str] = &["write", "open", "quit"];
@@ -970,27 +933,25 @@ pub fn prepend_to_line(cx: &mut Context) {
970pub fn append_to_line(cx: &mut Context) {
933pub fn append_to_line(cx: &mut Context) {
971 move_line_end(cx);
934 move_line_end(cx);
972
935
973− let view_id = cx.view_id;
936+ let (view, doc) = cx.current();
974− let doc = cx.doc();
975 enter_insert_mode(doc);
937 enter_insert_mode(doc);
976
938
977 // offset by another 1 char since move_line_end will position on the last char, we want to
939 // offset by another 1 char since move_line_end will position on the last char, we want to
978 // append past that
940 // append past that
979− let selection = doc.selection(view_id).transform(|range| {
941+ let selection = doc.selection(view.id).transform(|range| {
980 let pos = range.head + 1;
942 let pos = range.head + 1;
981 Range::new(pos, pos)
943 Range::new(pos, pos)
982 });
944 });
983− doc.set_selection(view_id, selection);
945+ doc.set_selection(view.id, selection);
984}
946}
985
947
986// o inserts a new line after each line with a selection
948// o inserts a new line after each line with a selection
987pub fn open_below(cx: &mut Context) {
949pub fn open_below(cx: &mut Context) {
988− let view_id = cx.view_id;
989 let count = cx.count;
950 let count = cx.count;
990− let doc = cx.doc();
951+ let (view, doc) = cx.current();
991 enter_insert_mode(doc);
952 enter_insert_mode(doc);
992
953
993− let lines = selection_lines(doc.text(), doc.selection(view_id));
954+ let lines = selection_lines(doc.text(), doc.selection(view.id));
994
955
995 let positions = lines.into_iter().map(|index| {
956 let positions = lines.into_iter().map(|index| {
996 // adjust all positions to the end of the line (next line minus one)
957 // adjust all positions to the end of the line (next line minus one)
@@ -1032,17 +993,16 @@ pub fn open_below(cx: &mut Context) {
1032 let transaction =
993 let transaction =
1033 Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
994 Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
1034
995
1035− doc.apply(&transaction, view_id);
996+ doc.apply(&transaction, view.id);
1036}
997}
1037
998
1038// O inserts a new line before each line with a selection
999// O inserts a new line before each line with a selection
1039pub fn open_above(cx: &mut Context) {
1000pub fn open_above(cx: &mut Context) {
1040− let view_id = cx.view_id;
1041 let count = cx.count;
1001 let count = cx.count;
1042− let doc = cx.doc();
1002+ let (view, doc) = cx.current();
1043 enter_insert_mode(doc);
1003 enter_insert_mode(doc);
1044
1004
1045− let lines = selection_lines(doc.text(), doc.selection(view_id));
1005+ let lines = selection_lines(doc.text(), doc.selection(view.id));
1046
1006
1047 let positions = lines.into_iter().map(|index| {
1007 let positions = lines.into_iter().map(|index| {
1048 // adjust all positions to the end of the previous line
1008 // adjust all positions to the end of the previous line
@@ -1085,27 +1045,26 @@ pub fn open_above(cx: &mut Context) {
1085 let transaction =
1045 let transaction =
1086 Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
1046 Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
1087
1047
1088− doc.apply(&transaction, view_id);
1048+ doc.apply(&transaction, view.id);
1089}
1049}
1090
1050
1091pub fn normal_mode(cx: &mut Context) {
1051pub fn normal_mode(cx: &mut Context) {
1092− let view_id = cx.view_id;
1052+ let (view, doc) = cx.current();
1093− let doc = cx.doc();
1094
1053
1095 doc.mode = Mode::Normal;
1054 doc.mode = Mode::Normal;
1096
1055
1097− doc.append_changes_to_history(view_id);
1056+ doc.append_changes_to_history(view.id);
1098
1057
1099 // if leaving append mode, move cursor back by 1
1058 // if leaving append mode, move cursor back by 1
1100 if doc.restore_cursor {
1059 if doc.restore_cursor {
1101 let text = doc.text().slice(..);
1060 let text = doc.text().slice(..);
1102− let selection = doc.selection(view_id).transform(|range| {
1061+ let selection = doc.selection(view.id).transform(|range| {
1103 Range::new(
1062 Range::new(
1104 range.from(),
1063 range.from(),
1105 graphemes::prev_grapheme_boundary(text, range.to()),
1064 graphemes::prev_grapheme_boundary(text, range.to()),
1106 )
1065 )
1107 });
1066 });
1108− doc.set_selection(view_id, selection);
1067+ doc.set_selection(view.id, selection);
1109
1068
1110 doc.restore_cursor = false;
1069 doc.restore_cursor = false;
1111 }
1070 }
@@ -1113,16 +1072,12 @@ pub fn normal_mode(cx: &mut Context) {
1113
1072
1114// Store a jump on the jumplist.
1073// Store a jump on the jumplist.
1115fn push_jump(cx: &mut Context) {
1074fn push_jump(cx: &mut Context) {
1116− let jump = {
1075+ let (view, doc) = cx.current();
1117− let view_id = cx.view_id;
1118− let doc = cx.doc();
1119− (doc.id(), doc.selection(view_id).clone())
1076+ let jump = { (doc.id(), doc.selection(view.id).clone()) };
1120− };
1121− cx.view().jumps.push(jump);
1077+ view.jumps.push(jump);
1122}
1078}
1123
1079
1124pub fn goto_mode(cx: &mut Context) {
1080pub fn goto_mode(cx: &mut Context) {
1125− let view_id = cx.view_id;
1126 let count = cx.count;
1081 let count = cx.count;
1127
1082
1128 if count > 1 {
1083 if count > 1 {
@@ -1130,9 +1085,9 @@ pub fn goto_mode(cx: &mut Context) {
1130
1085
1131 // TODO: can't go to line 1 since we can't distinguish between g and 1g, g gets converted
1086 // TODO: can't go to line 1 since we can't distinguish between g and 1g, g gets converted
1132 // to 1g
1087 // to 1g
1133− let doc = cx.doc();
1088+ let (view, doc) = cx.current();
1134 let pos = doc.text().line_to_char(count - 1);
1089 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));
1136 return;
1091 return;
1137 }
1092 }
1138
1093
@@ -1173,11 +1128,10 @@ fn _goto(cx: &mut Context, locations: Vec<lsp::Location>) {
1173 let id = editor
1128 let id = editor
1174 .open(PathBuf::from(location.uri.path()), action)
1129 .open(PathBuf::from(location.uri.path()), action)
1175 .expect("editor.open failed");
1130 .expect("editor.open failed");
1176− let view_id = editor.view().id;
1131+ let (view, doc) = editor.current();
1177− let doc = &mut editor.documents[id];
1178 let definition_pos = location.range.start;
1132 let definition_pos = location.range.start;
1179 let new_pos = helix_lsp::util::lsp_pos_to_pos(doc.text(), definition_pos);
1133 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));
1181 }
1135 }
1182
1136
1183 match locations.as_slice() {
1137 match locations.as_slice() {
@@ -1201,15 +1155,14 @@ fn _goto(cx: &mut Context, locations: Vec<lsp::Location>) {
1201}
1155}
1202
1156
1203pub fn goto_definition(cx: &mut Context) {
1157pub fn goto_definition(cx: &mut Context) {
1204− let view_id = cx.view_id;
1158+ let (view, doc) = cx.current();
1205− let doc = cx.doc();
1206 let language_server = match doc.language_server() {
1159 let language_server = match doc.language_server() {
1207 Some(language_server) => language_server,
1160 Some(language_server) => language_server,
1208 None => return,
1161 None => return,
1209 };
1162 };
1210
1163
1211 // TODO: blocking here is not ideal
1164 // 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());
1213
1166
1214 // TODO: handle fails
1167 // TODO: handle fails
1215 let res =
1168 let res =
@@ -1218,15 +1171,14 @@ pub fn goto_definition(cx: &mut Context) {
1218}
1171}
1219
1172
1220pub fn goto_type_definition(cx: &mut Context) {
1173pub fn goto_type_definition(cx: &mut Context) {
1221− let view_id = cx.view_id;
1174+ let (view, doc) = cx.current();
1222− let doc = cx.doc();
1223 let language_server = match doc.language_server() {
1175 let language_server = match doc.language_server() {
1224 Some(language_server) => language_server,
1176 Some(language_server) => language_server,
1225 None => return,
1177 None => return,
1226 };
1178 };
1227
1179
1228 // TODO: blocking here is not ideal
1180 // 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());
1230
1182
1231 // TODO: handle fails
1183 // TODO: handle fails
1232 let res = smol::block_on(language_server.goto_type_definition(doc.identifier(), pos))
1184 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) {
1235}
1187}
1236
1188
1237pub fn goto_implementation(cx: &mut Context) {
1189pub fn goto_implementation(cx: &mut Context) {
1238− let view_id = cx.view_id;
1190+ let (view, doc) = cx.current();
1239− let doc = cx.doc();
1240 let language_server = match doc.language_server() {
1191 let language_server = match doc.language_server() {
1241 Some(language_server) => language_server,
1192 Some(language_server) => language_server,
1242 None => return,
1193 None => return,
1243 };
1194 };
1244
1195
1245 // TODO: blocking here is not ideal
1196 // 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());
1247
1198
1248 // TODO: handle fails
1199 // TODO: handle fails
1249 let res = smol::block_on(language_server.goto_implementation(doc.identifier(), pos))
1200 let res = smol::block_on(language_server.goto_implementation(doc.identifier(), pos))
@@ -1252,15 +1203,14 @@ pub fn goto_implementation(cx: &mut Context) {
1252}
1203}
1253
1204
1254pub fn goto_reference(cx: &mut Context) {
1205pub fn goto_reference(cx: &mut Context) {
1255− let view_id = cx.view_id;
1206+ let (view, doc) = cx.current();
1256− let doc = cx.doc();
1257 let language_server = match doc.language_server() {
1207 let language_server = match doc.language_server() {
1258 Some(language_server) => language_server,
1208 Some(language_server) => language_server,
1259 None => return,
1209 None => return,
1260 };
1210 };
1261
1211
1262 // TODO: blocking here is not ideal
1212 // 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());
1264
1214
1265 // TODO: handle fails
1215 // TODO: handle fails
1266 let res =
1216 let res =
@@ -1269,8 +1219,7 @@ pub fn goto_reference(cx: &mut Context) {
1269}
1219}
1270
1220
1271pub fn signature_help(cx: &mut Context) {
1221pub fn signature_help(cx: &mut Context) {
1272− let view_id = cx.view_id;
1222+ let (view, doc) = cx.current();
1273− let doc = cx.doc();
1274
1223
1275 let language_server = match doc.language_server() {
1224 let language_server = match doc.language_server() {
1276 Some(language_server) => language_server,
1225 Some(language_server) => language_server,
@@ -1278,7 +1227,7 @@ pub fn signature_help(cx: &mut Context) {
1278 };
1227 };
1279
1228
1280 // TODO: blocking here is not ideal
1229 // 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());
1282
1231
1283 // TODO: handle fails
1232 // TODO: handle fails
1284
1233
@@ -1371,21 +1320,20 @@ pub mod insert {
1371
1320
1372 // TODO: insert means add text just before cursor, on exit we should be on the last letter.
1321 // TODO: insert means add text just before cursor, on exit we should be on the last letter.
1373 pub fn insert_char(cx: &mut Context, c: char) {
1322 pub fn insert_char(cx: &mut Context, c: char) {
1374− let view_id = cx.view_id;
1323+ let (view, doc) = cx.current();
1375− let doc = cx.doc();
1376
1324
1377 // run through insert hooks, stopping on the first one that returns Some(t)
1325 // run through insert hooks, stopping on the first one that returns Some(t)
1378 for hook in HOOKS {
1326 for hook in HOOKS {
1379− if let Some(transaction) = hook(doc.text(), doc.selection(view_id), c) {
1327+ if let Some(transaction) = hook(doc.text(), doc.selection(view.id), c) {
1380− doc.apply(&transaction, view_id);
1328+ doc.apply(&transaction, view.id);
1381 return;
1329 return;
1382 }
1330 }
1383 }
1331 }
1384
1332
1385 let t = Tendril::from_char(c);
1333 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);
1387
1335
1388− doc.apply(&transaction, view_id);
1336+ doc.apply(&transaction, view.id);
1389
1337
1390 // TODO: need a post insert hook too for certain triggers (autocomplete, signature help, etc)
1338 // TODO: need a post insert hook too for certain triggers (autocomplete, signature help, etc)
1391 // this could also generically look at Transaction, but it's a bit annoying to look at
1339 // this could also generically look at Transaction, but it's a bit annoying to look at
@@ -1396,22 +1344,20 @@ pub mod insert {
1396 }
1344 }
1397
1345
1398 pub fn insert_tab(cx: &mut Context) {
1346 pub fn insert_tab(cx: &mut Context) {
1399− let view_id = cx.view_id;
1347+ let (view, doc) = cx.current();
1400− let doc = cx.doc();
1401 // TODO: round out to nearest indentation level (for example a line with 3 spaces should
1348 // TODO: round out to nearest indentation level (for example a line with 3 spaces should
1402 // indent by one to reach 4 spaces).
1349 // indent by one to reach 4 spaces).
1403
1350
1404 let indent = Tendril::from(doc.indent_unit());
1351 let indent = Tendril::from(doc.indent_unit());
1405− let transaction = Transaction::insert(doc.text(), doc.selection(view_id), indent);
1352+ let transaction = Transaction::insert(doc.text(), doc.selection(view.id), indent);
1406− doc.apply(&transaction, view_id);
1353+ doc.apply(&transaction, view.id);
1407 }
1354 }
1408
1355
1409 pub fn insert_newline(cx: &mut Context) {
1356 pub fn insert_newline(cx: &mut Context) {
1410− let view_id = cx.view_id;
1357+ let (view, doc) = cx.current();
1411− let doc = cx.doc();
1412 let text = doc.text().slice(..);
1358 let text = doc.text().slice(..);
1413 let transaction =
1359 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| {
1415 // TODO: offset range.head by 1? when calculating?
1361 // TODO: offset range.head by 1? when calculating?
1416 let indent_level = helix_core::indent::suggested_indent_for_pos(
1362 let indent_level = helix_core::indent::suggested_indent_for_pos(
1417 doc.syntax(),
1363 doc.syntax(),
@@ -1425,40 +1371,39 @@ pub mod insert {
1425 text.push_str(&indent);
1371 text.push_str(&indent);
1426 (range.head, range.head, Some(text.into()))
1372 (range.head, range.head, Some(text.into()))
1427 });
1373 });
1428− doc.apply(&transaction, view_id);
1374+ doc.apply(&transaction, view.id);
1429 }
1375 }
1430
1376
1431 // TODO: handle indent-aware delete
1377 // TODO: handle indent-aware delete
1432 pub fn delete_char_backward(cx: &mut Context) {
1378 pub fn delete_char_backward(cx: &mut Context) {
1433− let view_id = cx.view_id;
1434 let count = cx.count;
1379 let count = cx.count;
1435− let doc = cx.doc();
1380+ let (view, doc) = cx.current();
1436 let text = doc.text().slice(..);
1381 let text = doc.text().slice(..);
1437 let transaction =
1382 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| {
1439 (
1384 (
1440 graphemes::nth_prev_grapheme_boundary(text, range.head, count),
1385 graphemes::nth_prev_grapheme_boundary(text, range.head, count),
1441 range.head,
1386 range.head,
1442 None,
1387 None,
1443 )
1388 )
1444 });
1389 });
1445− doc.apply(&transaction, view_id);
1390+ doc.apply(&transaction, view.id);
1446 }
1391 }
1447
1392
1448 pub fn delete_char_forward(cx: &mut Context) {
1393 pub fn delete_char_forward(cx: &mut Context) {
1449− let view_id = cx.view_id;
1450 let count = cx.count;
1394 let count = cx.count;
1451 let doc = cx.doc();
1395 let doc = cx.doc();
1396+ let (view, doc) = cx.current();
1452 let text = doc.text().slice(..);
1397 let text = doc.text().slice(..);
1453 let transaction =
1398 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| {
1455 (
1400 (
1456 range.head,
1401 range.head,
1457 graphemes::nth_next_grapheme_boundary(text, range.head, count),
1402 graphemes::nth_next_grapheme_boundary(text, range.head, count),
1458 None,
1403 None,
1459 )
1404 )
1460 });
1405 });
1461− doc.apply(&transaction, view_id);
1406+ doc.apply(&transaction, view.id);
1462 }
1407 }
1463}
1408}
1464
1409
@@ -1481,10 +1426,9 @@ pub fn redo(cx: &mut Context) {
1481
1426
1482pub fn yank(cx: &mut Context) {
1427pub fn yank(cx: &mut Context) {
1483 // TODO: should selections be made end inclusive?
1428 // TODO: should selections be made end inclusive?
1484− let view_id = cx.view_id;
1429+ let (view, doc) = cx.current();
1485− let doc = cx.doc();
1486 let values: Vec<String> = doc
1430 let values: Vec<String> = doc
1487− .selection(view_id)
1431+ .selection(view.id)
1488 .fragments(doc.text().slice(..))
1432 .fragments(doc.text().slice(..))
1489 .map(Cow::into_owned)
1433 .map(Cow::into_owned)
1490 .collect();
1434 .collect();
@@ -1527,25 +1471,24 @@ pub fn paste(cx: &mut Context) {
1527
1471
1528 let mut values = values.into_iter().map(Tendril::from).chain(repeat);
1472 let mut values = values.into_iter().map(Tendril::from).chain(repeat);
1529
1473
1530− let view_id = cx.view_id;
1474+ let (view, doc) = cx.current();
1531− let doc = cx.doc();
1532
1475
1533 let transaction = if linewise {
1476 let transaction = if linewise {
1534 // paste on the next line
1477 // paste on the next line
1535 // TODO: can simply take a range + modifier and compute the right pos without ifs
1478 // TODO: can simply take a range + modifier and compute the right pos without ifs
1536 let text = doc.text();
1479 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| {
1538 let line_end = text.line_to_char(text.char_to_line(range.head) + 1);
1481 let line_end = text.line_to_char(text.char_to_line(range.head) + 1);
1539 (line_end, line_end, Some(values.next().unwrap()))
1482 (line_end, line_end, Some(values.next().unwrap()))
1540 })
1483 })
1541 } else {
1484 } 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| {
1543 (range.head + 1, range.head + 1, Some(values.next().unwrap()))
1486 (range.head + 1, range.head + 1, Some(values.next().unwrap()))
1544 })
1487 })
1545 };
1488 };
1546
1489
1547− doc.apply(&transaction, view_id);
1490+ doc.apply(&transaction, view.id);
1548− doc.append_changes_to_history(view_id);
1491+ doc.append_changes_to_history(view.id);
1549 }
1492 }
1550}
1493}
1551
1494
@@ -1567,9 +1510,8 @@ fn get_lines(doc: &Document, view_id: ViewId) -> Vec<usize> {
1567}
1510}
1568
1511
1569pub fn indent(cx: &mut Context) {
1512pub fn indent(cx: &mut Context) {
1570− let view_id = cx.view_id;
1513+ let (view, doc) = cx.current();
1571− let doc = cx.doc();
1572− let lines = get_lines(doc, view_id);
1514+ let lines = get_lines(doc, view.id);
1573
1515
1574 // Indent by one level
1516 // Indent by one level
1575 let indent = Tendril::from(doc.indent_unit());
1517 let indent = Tendril::from(doc.indent_unit());
@@ -1581,14 +1523,13 @@ pub fn indent(cx: &mut Context) {
1581 (pos, pos, Some(indent.clone()))
1523 (pos, pos, Some(indent.clone()))
1582 }),
1524 }),
1583 );
1525 );
1584− doc.apply(&transaction, view_id);
1526+ doc.apply(&transaction, view.id);
1585− doc.append_changes_to_history(view_id);
1527+ doc.append_changes_to_history(view.id);
1586}
1528}
1587
1529
1588pub fn unindent(cx: &mut Context) {
1530pub fn unindent(cx: &mut Context) {
1589− let view_id = cx.view_id;
1531+ let (view, doc) = cx.current();
1590− let doc = cx.doc();
1591− let lines = get_lines(doc, view_id);
1532+ let lines = get_lines(doc, view.id);
1592 let mut changes = Vec::with_capacity(lines.len());
1533 let mut changes = Vec::with_capacity(lines.len());
1593 let tab_width = doc.tab_width();
1534 let tab_width = doc.tab_width();
1594
1535
@@ -1616,14 +1557,13 @@ pub fn unindent(cx: &mut Context) {
1616
1557
1617 let transaction = Transaction::change(doc.text(), changes.into_iter());
1558 let transaction = Transaction::change(doc.text(), changes.into_iter());
1618
1559
1619− doc.apply(&transaction, view_id);
1560+ doc.apply(&transaction, view.id);
1620− doc.append_changes_to_history(view_id);
1561+ doc.append_changes_to_history(view.id);
1621}
1562}
1622
1563
1623pub fn format_selections(cx: &mut Context) {
1564pub fn format_selections(cx: &mut Context) {
1624 use helix_lsp::lsp;
1565 use helix_lsp::lsp;
1625− let view_id = cx.view_id;
1566+ let (view, doc) = cx.current();
1626− let doc = cx.doc();
1627
1567
1628 // via lsp if available
1568 // via lsp if available
1629 // else via tree-sitter indentation calculations
1569 // else via tree-sitter indentation calculations
@@ -1631,7 +1571,7 @@ pub fn format_selections(cx: &mut Context) {
1631 // TODO: blocking here is not ideal
1571 // TODO: blocking here is not ideal
1632
1572
1633 let ranges: Vec<lsp::Range> = doc
1573 let ranges: Vec<lsp::Range> = doc
1634− .selection(view_id)
1574+ .selection(view.id)
1635 .iter()
1575 .iter()
1636 .map(|range| helix_lsp::util::range_to_lsp_range(doc.text(), *range))
1576 .map(|range| helix_lsp::util::range_to_lsp_range(doc.text(), *range))
1637 .collect();
1577 .collect();
@@ -1653,23 +1593,22 @@ pub fn format_selections(cx: &mut Context) {
1653
1593
1654 let transaction = helix_lsp::util::generate_transaction_from_edits(doc.text(), edits);
1594 let transaction = helix_lsp::util::generate_transaction_from_edits(doc.text(), edits);
1655
1595
1656− doc.apply(&transaction, view_id);
1596+ doc.apply(&transaction, view.id);
1657 }
1597 }
1658
1598
1659− doc.append_changes_to_history(view_id);
1599+ doc.append_changes_to_history(view.id);
1660}
1600}
1661
1601
1662pub fn join_selections(cx: &mut Context) {
1602pub fn join_selections(cx: &mut Context) {
1663 use movement::skip_over_next;
1603 use movement::skip_over_next;
1664− let view_id = cx.view_id;
1604+ let (view, doc) = cx.current();
1665− let doc = cx.doc();
1666 let text = doc.text();
1605 let text = doc.text();
1667 let slice = doc.text().slice(..);
1606 let slice = doc.text().slice(..);
1668
1607
1669 let mut changes = Vec::new();
1608 let mut changes = Vec::new();
1670 let fragment = Tendril::from(" ");
1609 let fragment = Tendril::from(" ");
1671
1610
1672− for selection in doc.selection(view_id) {
1611+ for selection in doc.selection(view.id) {
1673 let start = text.char_to_line(selection.from());
1612 let start = text.char_to_line(selection.from());
1674 let mut end = text.char_to_line(selection.to());
1613 let mut end = text.char_to_line(selection.to());
1675 if start == end {
1614 if start == end {
@@ -1700,8 +1639,8 @@ pub fn join_selections(cx: &mut Context) {
1700 // TODO: select inserted spaces
1639 // TODO: select inserted spaces
1701 // .with_selection(selection);
1640 // .with_selection(selection);
1702
1641
1703− doc.apply(&transaction, view_id);
1642+ doc.apply(&transaction, view.id);
1704− doc.append_changes_to_history(view_id);
1643+ doc.append_changes_to_history(view.id);
1705}
1644}
1706
1645
1707pub fn keep_selections(cx: &mut Context) {
1646pub fn keep_selections(cx: &mut Context) {
@@ -1719,12 +1658,11 @@ pub fn keep_selections(cx: &mut Context) {
1719}
1658}
1720
1659
1721pub fn keep_primary_selection(cx: &mut Context) {
1660pub fn keep_primary_selection(cx: &mut Context) {
1722− let view_id = cx.view_id;
1661+ let (view, doc) = cx.current();
1723− let doc = cx.doc();
1724
1662
1725− let range = doc.selection(view_id).primary();
1663+ let range = doc.selection(view.id).primary();
1726 let selection = Selection::single(range.anchor, range.head);
1664 let selection = Selection::single(range.anchor, range.head);
1727− doc.set_selection(view_id, selection);
1665+ doc.set_selection(view.id, selection);
1728}
1666}
1729
1667
1730//
1668//
@@ -1773,8 +1711,7 @@ pub fn completion(cx: &mut Context) {
1773 // The prefix still has to satisfy `company-minimum-prefix-length' before that
1711 // The prefix still has to satisfy `company-minimum-prefix-length' before that
1774 // happens. The value of nil means no idle completion."
1712 // happens. The value of nil means no idle completion."
1775
1713
1776− let view_id = cx.view_id;
1714+ let (view, doc) = cx.current();
1777− let doc = cx.doc();
1778
1715
1779 let language_server = match doc.language_server() {
1716 let language_server = match doc.language_server() {
1780 Some(language_server) => language_server,
1717 Some(language_server) => language_server,
@@ -1782,13 +1719,13 @@ pub fn completion(cx: &mut Context) {
1782 };
1719 };
1783
1720
1784 // TODO: blocking here is not ideal
1721 // 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());
1786
1723
1787 // TODO: handle fails
1724 // TODO: handle fails
1788
1725
1789 let res = smol::block_on(language_server.completion(doc.identifier(), pos)).unwrap();
1726 let res = smol::block_on(language_server.completion(doc.identifier(), pos)).unwrap();
1790
1727
1791− let trigger_offset = doc.selection(view_id).cursor();
1728+ let trigger_offset = doc.selection(view.id).cursor();
1792
1729
1793 cx.callback(
1730 cx.callback(
1794 res,
1731 res,
@@ -1825,8 +1762,7 @@ pub fn completion(cx: &mut Context) {
1825pub fn hover(cx: &mut Context) {
1762pub fn hover(cx: &mut Context) {
1826 use helix_lsp::lsp;
1763 use helix_lsp::lsp;
1827
1764
1828− let view_id = cx.view_id;
1765+ let (view, doc) = cx.current();
1829− let doc = cx.doc();
1830
1766
1831 let language_server = match doc.language_server() {
1767 let language_server = match doc.language_server() {
1832 Some(language_server) => language_server,
1768 Some(language_server) => language_server,
@@ -1837,7 +1773,7 @@ pub fn hover(cx: &mut Context) {
1837
1773
1838 // TODO: blocking here is not ideal, make commands async fn?
1774 // TODO: blocking here is not ideal, make commands async fn?
1839 // not like we can process additional input meanwhile though
1775 // 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());
1841
1777
1842 // TODO: handle fails
1778 // TODO: handle fails
1843 let res = smol::block_on(language_server.text_document_hover(doc.identifier(), pos))
1779 let res = smol::block_on(language_server.text_document_hover(doc.identifier(), pos))
@@ -1873,36 +1809,33 @@ pub fn next_view(cx: &mut Context) {
1873
1809
1874// comments
1810// comments
1875pub fn toggle_comments(cx: &mut Context) {
1811pub fn toggle_comments(cx: &mut Context) {
1876− let view_id = cx.view_id;
1812+ let (view, doc) = cx.current();
1877− let doc = cx.doc();
1878− let transaction = comment::toggle_line_comments(doc.text(), doc.selection(view_id));
1813+ let transaction = comment::toggle_line_comments(doc.text(), doc.selection(view.id));
1879
1814
1880− doc.apply(&transaction, view_id);
1815+ doc.apply(&transaction, view.id);
1881− doc.append_changes_to_history(view_id);
1816+ doc.append_changes_to_history(view.id);
1882}
1817}
1883
1818
1884// tree sitter node selection
1819// tree sitter node selection
1885
1820
1886pub fn expand_selection(cx: &mut Context) {
1821pub fn expand_selection(cx: &mut Context) {
1887− let view_id = cx.view_id;
1822+ let (view, doc) = cx.current();
1888− let doc = cx.doc();
1889
1823
1890 if let Some(syntax) = doc.syntax() {
1824 if let Some(syntax) = doc.syntax() {
1891 let text = doc.text().slice(..);
1825 let text = doc.text().slice(..);
1892− let selection = object::expand_selection(syntax, text, doc.selection(view_id));
1826+ let selection = object::expand_selection(syntax, text, doc.selection(view.id));
1893− doc.set_selection(view_id, selection);
1827+ doc.set_selection(view.id, selection);
1894 }
1828 }
1895}
1829}
1896
1830
1897pub fn match_brackets(cx: &mut Context) {
1831pub fn match_brackets(cx: &mut Context) {
1898− let view_id = cx.view_id;
1832+ let (view, doc) = cx.current();
1899− let doc = cx.doc();
1900
1833
1901 if let Some(syntax) = doc.syntax() {
1834 if let Some(syntax) = doc.syntax() {
1902− let pos = doc.selection(view_id).cursor();
1835+ let pos = doc.selection(view.id).cursor();
1903 if let Some(pos) = match_brackets::find(syntax, doc.text(), pos) {
1836 if let Some(pos) = match_brackets::find(syntax, doc.text(), pos) {
1904 let selection = Selection::point(pos);
1837 let selection = Selection::point(pos);
1905− doc.set_selection(view_id, selection);
1838+ doc.set_selection(view.id, selection);
1906 };
1839 };
1907 }
1840 }
1908}
1841}
@@ -1922,16 +1855,14 @@ pub fn jump_forward(cx: &mut Context) {
1922
1855
1923pub fn jump_backward(cx: &mut Context) {
1856pub fn jump_backward(cx: &mut Context) {
1924 let count = cx.count;
1857 let count = cx.count;
1925− let view = cx.view();
1858+ let (view, doc) = cx.current();
1926
1859
1927 if let Some((id, selection)) = view.jumps.backward(count) {
1860 if let Some((id, selection)) = view.jumps.backward(count) {
1928 // TODO: position first_line so that main cursor is centered
1861 // TODO: position first_line so that main cursor is centered
1929 view.first_line = 0;
1862 view.first_line = 0;
1930 view.doc = *id;
1863 view.doc = *id;
1931 let selection = selection.clone();
1864 let selection = selection.clone();
1932− let view_id = view.id;
1865+ doc.set_selection(view.id, selection);
1933− let doc = cx.doc();
1934− doc.set_selection(view_id, selection);
1935 };
1866 };
1936}
1867}
1937
1868
helix-term/src/ui/completion.rs+6−12
@@ -44,10 +44,7 @@ impl Completion {
44 // doc.state = snapshot.clone();
44 // doc.state = snapshot.clone();
45 }
45 }
46 PromptEvent::Validate => {
46 PromptEvent::Validate => {
47− let view = editor.view();
47+ let (view, doc) = editor.current();
48− let view_id = view.id;
49− let id = view.doc;
50− let doc = &mut editor.documents[id];
51
48
52 // revert state to what it was before the last update
49 // revert state to what it was before the last update
53 // doc.state = snapshot.clone();
50 // doc.state = snapshot.clone();
@@ -92,18 +89,18 @@ impl Completion {
92 }
89 }
93
90
94 // if more text was entered, remove it
91 // if more text was entered, remove it
95− let cursor = doc.selection(view_id).cursor();
92+ let cursor = doc.selection(view.id).cursor();
96 if trigger_offset < cursor {
93 if trigger_offset < cursor {
97 let remove = Transaction::change(
94 let remove = Transaction::change(
98 doc.text(),
95 doc.text(),
99 vec![(trigger_offset, cursor, None)].into_iter(),
96 vec![(trigger_offset, cursor, None)].into_iter(),
100 );
97 );
101− doc.apply(&remove, view_id);
98+ doc.apply(&remove, view.id);
102 }
99 }
103
100
104 let transaction =
101 let transaction =
105 util::generate_transaction_from_edits(doc.text(), vec![edit]);
102 util::generate_transaction_from_edits(doc.text(), vec![edit]);
106− doc.apply(&transaction, view_id);
103+ doc.apply(&transaction, view.id);
107 }
104 }
108 _ => (),
105 _ => (),
109 };
106 };
@@ -127,10 +124,7 @@ impl Component for Completion {
127 {
124 {
128 // recompute menu based on matches
125 // recompute menu based on matches
129 let menu = self.popup.contents();
126 let menu = self.popup.contents();
130− let view = cx.editor.view();
127+ let (view, doc) = cx.editor.current();
131− let view_id = view.id;
132− let id = view.doc;
133− let doc = cx.editor.document(id).unwrap();
134
128
135 // cx.hooks()
129 // cx.hooks()
136 // cx.add_hook(enum type, ||)
130 // cx.add_hook(enum type, ||)
@@ -142,7 +136,7 @@ impl Component for Completion {
142 // TODO: hooks should get processed immediately so maybe do it after select!(), before
136 // TODO: hooks should get processed immediately so maybe do it after select!(), before
143 // looping?
137 // looping?
144
138
145− let cursor = doc.selection(view_id).cursor();
139+ let cursor = doc.selection(view.id).cursor();
146 if self.trigger_offset <= cursor {
140 if self.trigger_offset <= cursor {
147 let fragment = doc.text().slice(self.trigger_offset..cursor);
141 let fragment = doc.text().slice(self.trigger_offset..cursor);
148 // ^ problem seems to be that we handle events here before the editor layer, so the
142 // ^ problem seems to be that we handle events here before the editor layer, so the
helix-term/src/ui/editor.rs+6−7
@@ -487,14 +487,12 @@ impl Component for EditorView {
487 EventResult::Consumed(None)
487 EventResult::Consumed(None)
488 }
488 }
489 Event::Key(event) => {
489 Event::Key(event) => {
490− let view = cx.editor.view();
490+ let (view, doc) = cx.editor.current();
491− let view_id = view.id;
491+ let mode = doc.mode();
492− let id = view.doc;
493− let mode = cx.editor.document(id).unwrap().mode();
494
492
495 let mut cxt = commands::Context {
493 let mut cxt = commands::Context {
494+ view_id: view.id,
496 editor: &mut cx.editor,
495 editor: &mut cx.editor,
497− view_id,
498 count: 1,
496 count: 1,
499 callback: None,
497 callback: None,
500 callbacks: cx.callbacks,
498 callbacks: cx.callbacks,
@@ -524,9 +522,10 @@ impl Component for EditorView {
524 // appease borrowck
522 // appease borrowck
525 let callback = cxt.callback.take();
523 let callback = cxt.callback.take();
526
524
525+ let (view, doc) = cx.editor.current();
527− cx.editor.ensure_cursor_in_view(cx.editor.tree.focus);
526+ view.ensure_cursor_in_view(doc);
528
527
529− if mode == Mode::Normal && cx.editor.document(id).unwrap().mode() == Mode::Insert {
528+ if mode == Mode::Normal && doc.mode() == Mode::Insert {
530 // HAXX: if we just entered insert mode from normal, clear key buf
529 // HAXX: if we just entered insert mode from normal, clear key buf
531 // and record the command that got us into this mode.
530 // and record the command that got us into this mode.
532
531
helix-term/src/ui/mod.rs+5−12
@@ -45,11 +45,8 @@ pub fn regex_prompt(
45 match event {
45 match event {
46 PromptEvent::Abort => {
46 PromptEvent::Abort => {
47 // TODO: also revert text
47 // TODO: also revert text
48− let view = editor.view();
48+ let (view, doc) = editor.current();
49− let view_id = view.id;
50− let id = view.doc;
51− let doc = &mut editor.documents[id];
52− doc.set_selection(view_id, snapshot.clone());
49+ doc.set_selection(view.id, snapshot.clone());
53 }
50 }
54 PromptEvent::Validate => {
51 PromptEvent::Validate => {
55 // TODO: push_jump to store selection just before jump
52 // TODO: push_jump to store selection just before jump
@@ -62,19 +59,15 @@ pub fn regex_prompt(
62
59
63 match Regex::new(input) {
60 match Regex::new(input) {
64 Ok(regex) => {
61 Ok(regex) => {
65− // let view = &mut editor.view_mut();
62+ let (view, doc) = editor.current();
66− let view = editor.view();
67− let view_id = view.id;
68− let id = view.doc;
69− let doc = &mut editor.documents[id];
70
63
71 // revert state to what it was before the last update
64 // revert state to what it was before the last update
72 // TODO: also revert text
65 // TODO: also revert text
73− doc.set_selection(view_id, snapshot.clone());
66+ doc.set_selection(view.id, snapshot.clone());
74
67
75 fun(doc, regex);
68 fun(doc, regex);
76
69
77− editor.ensure_cursor_in_view(view_id);
70+ view.ensure_cursor_in_view(doc);
78 }
71 }
79 Err(_err) => (), // TODO: mark command line as error
72 Err(_err) => (), // TODO: mark command line as error
80 }
73 }
helix-view/src/editor.rs+6
@@ -172,6 +172,12 @@ impl Editor {
172 self.tree.is_empty()
172 self.tree.is_empty()
173 }
173 }
174
174
175+ pub fn current(&mut self) -> (&mut View, &mut Document) {
176+ let view = self.tree.get_mut(self.tree.focus);
177+ let doc = &mut self.documents[view.doc];
178+ (view, doc)
179+ }
180+
175 pub fn view(&self) -> &View {
181 pub fn view(&self) -> &View {
176 self.tree.get(self.tree.focus)
182 self.tree.get(self.tree.focus)
177 }
183 }