on master help sign in
Make `Selection`'s normalize and transform methods self-consuming only.
7c7be6dNathan Vegdahl
helix-core/src/object.rs+1−1
@@ -6,7 +6,7 @@ use smallvec::smallvec;
6pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: &Selection) -> Selection {
6pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: &Selection) -> Selection {
7 let tree = syntax.tree();
7 let tree = syntax.tree();
8
8
9− selection.clone().transformed(|range| {
9+ selection.clone().transform(|range| {
10 let from = text.char_to_byte(range.from());
10 let from = text.char_to_byte(range.from());
11 let to = text.char_to_byte(range.to());
11 let to = text.char_to_byte(range.to());
12
12
helix-core/src/selection.rs+4−21
@@ -261,7 +261,7 @@ impl Selection {
261
261
262 pub fn push(mut self, range: Range) -> Self {
262 pub fn push(mut self, range: Range) -> Self {
263 self.ranges.push(range);
263 self.ranges.push(range);
264− self.normalized()
264+ self.normalize()
265 }
265 }
266 // replace_range
266 // replace_range
267
267
@@ -308,7 +308,7 @@ impl Selection {
308 }
308 }
309
309
310 /// Normalizes a `Selection`.
310 /// Normalizes a `Selection`.
311− pub fn normalize(&mut self) -> &mut Self {
311+ pub fn normalize(mut self) -> Self {
312 let primary = self.ranges[self.primary_index];
312 let primary = self.ranges[self.primary_index];
313 self.ranges.sort_unstable_by_key(Range::from);
313 self.ranges.sort_unstable_by_key(Range::from);
314 self.primary_index = self
314 self.primary_index = self
@@ -335,13 +335,6 @@ impl Selection {
335 self
335 self
336 }
336 }
337
337
338− /// Normalizes a `Selection`.
339− #[must_use]
340− pub fn normalized(mut self) -> Self {
341− self.normalize();
342− self
343− }
344−
345 // TODO: consume an iterator or a vec to reduce allocations?
338 // TODO: consume an iterator or a vec to reduce allocations?
346 #[must_use]
339 #[must_use]
347 pub fn new(ranges: SmallVec<[Range; 1]>, primary_index: usize) -> Self {
340 pub fn new(ranges: SmallVec<[Range; 1]>, primary_index: usize) -> Self {
@@ -355,14 +348,14 @@ impl Selection {
355
348
356 if selection.ranges.len() > 1 {
349 if selection.ranges.len() > 1 {
357 // TODO: only normalize if needed (any ranges out of order)
350 // TODO: only normalize if needed (any ranges out of order)
358− selection.normalize();
351+ selection = selection.normalize();
359 }
352 }
360
353
361 selection
354 selection
362 }
355 }
363
356
364 /// Takes a closure and maps each `Range` over the closure.
357 /// Takes a closure and maps each `Range` over the closure.
365− pub fn transform<F>(&mut self, f: F) -> &mut Self
358+ pub fn transform<F>(mut self, f: F) -> Self
366 where
359 where
367 F: Fn(Range) -> Range,
360 F: Fn(Range) -> Range,
368 {
361 {
@@ -373,16 +366,6 @@ impl Selection {
373 self
366 self
374 }
367 }
375
368
376− /// Takes a closure and maps each `Range` over the closure.
377− #[must_use]
378− pub fn transformed<F>(mut self, f: F) -> Self
379− where
380− F: Fn(Range) -> Range,
381− {
382− self.transform(f);
383− self
384− }
385−
386 pub fn fragments<'a>(&'a self, text: RopeSlice<'a>) -> impl Iterator<Item = Cow<str>> + 'a {
369 pub fn fragments<'a>(&'a self, text: RopeSlice<'a>) -> impl Iterator<Item = Cow<str>> + 'a {
387 self.ranges.iter().map(move |range| range.fragment(text))
370 self.ranges.iter().map(move |range| range.fragment(text))
388 }
371 }
helix-term/src/commands.rs+288−163
@@ -310,81 +310,119 @@ impl PartialEq for Command {
310fn move_char_left(cx: &mut Context) {
310fn move_char_left(cx: &mut Context) {
311 let count = cx.count();
311 let count = cx.count();
312 let (view, doc) = current!(cx.editor);
312 let (view, doc) = current!(cx.editor);
313− let (text, selection) = doc.text_and_mut_selection(view.id);
313+ doc.set_selection(
314+ view.id,
314− selection.transform(|range| {
315+ doc.selection(view.id).clone().transform(|range| {
315− movement::move_horizontally(text, range, Direction::Backward, count, Movement::Move)
316+ movement::move_horizontally(
317+ doc.text().slice(..),
318+ range,
319+ Direction::Backward,
320+ count,
321+ Movement::Move,
322+ )
316− });
323+ }),
324+ );
317}
325}
318
326
319fn move_char_right(cx: &mut Context) {
327fn move_char_right(cx: &mut Context) {
320 let count = cx.count();
328 let count = cx.count();
321 let (view, doc) = current!(cx.editor);
329 let (view, doc) = current!(cx.editor);
322− let (text, selection) = doc.text_and_mut_selection(view.id);
330+ doc.set_selection(
331+ view.id,
323− selection.transform(|range| {
332+ doc.selection(view.id).clone().transform(|range| {
324− movement::move_horizontally(text, range, Direction::Forward, count, Movement::Move)
333+ movement::move_horizontally(
334+ doc.text().slice(..),
335+ range,
336+ Direction::Forward,
337+ count,
338+ Movement::Move,
339+ )
325− });
340+ }),
341+ );
326}
342}
327
343
328fn move_line_up(cx: &mut Context) {
344fn move_line_up(cx: &mut Context) {
329 let count = cx.count();
345 let count = cx.count();
330 let (view, doc) = current!(cx.editor);
346 let (view, doc) = current!(cx.editor);
331− let (text, selection) = doc.text_and_mut_selection(view.id);
347+ doc.set_selection(
348+ view.id,
332− selection.transform(|range| {
349+ doc.selection(view.id).clone().transform(|range| {
333− movement::move_vertically(text, range, Direction::Backward, count, Movement::Move)
350+ movement::move_vertically(
351+ doc.text().slice(..),
352+ range,
353+ Direction::Backward,
354+ count,
355+ Movement::Move,
356+ )
334− });
357+ }),
358+ );
335}
359}
336
360
337fn move_line_down(cx: &mut Context) {
361fn move_line_down(cx: &mut Context) {
338 let count = cx.count();
362 let count = cx.count();
339 let (view, doc) = current!(cx.editor);
363 let (view, doc) = current!(cx.editor);
340− let (text, selection) = doc.text_and_mut_selection(view.id);
364+ doc.set_selection(
365+ view.id,
341− selection.transform(|range| {
366+ doc.selection(view.id).clone().transform(|range| {
342− movement::move_vertically(text, range, Direction::Forward, count, Movement::Move)
367+ movement::move_vertically(
368+ doc.text().slice(..),
369+ range,
370+ Direction::Forward,
371+ count,
372+ Movement::Move,
373+ )
343− });
374+ }),
375+ );
344}
376}
345
377
346fn move_line_end(cx: &mut Context) {
378fn move_line_end(cx: &mut Context) {
347 let (view, doc) = current!(cx.editor);
379 let (view, doc) = current!(cx.editor);
380+ doc.set_selection(
381+ view.id,
382+ doc.selection(view.id).clone().transform(|range| {
383+ let text = doc.text();
384+ let line = text.char_to_line(range.head);
348
385
349− let (text, selection) = doc.text_and_mut_selection(view.id);
350− selection.transform(|range| {
351− let line = text.char_to_line(range.head);
352−
353− let pos = line_end_char_index(&text.slice(..), line);
386+ let pos = line_end_char_index(&text.slice(..), line);
354− let pos = graphemes::nth_prev_grapheme_boundary(text.slice(..), pos, 1);
387+ let pos = graphemes::nth_prev_grapheme_boundary(text.slice(..), pos, 1);
355− let pos = range.head.max(pos).max(text.line_to_char(line));
388+ let pos = range.head.max(pos).max(text.line_to_char(line));
356
389
357− Range::new(pos, pos)
390+ Range::new(pos, pos)
358− });
391+ }),
392+ );
359}
393}
360
394
361fn move_line_start(cx: &mut Context) {
395fn move_line_start(cx: &mut Context) {
362 let (view, doc) = current!(cx.editor);
396 let (view, doc) = current!(cx.editor);
397+ doc.set_selection(
398+ view.id,
399+ doc.selection(view.id).clone().transform(|range| {
400+ let text = doc.text();
401+ let line = text.char_to_line(range.head);
363
402
364− let (text, selection) = doc.text_and_mut_selection(view.id);
365− selection.transform(|range| {
366− let line = text.char_to_line(range.head);
367−
368− // adjust to start of the line
403+ // adjust to start of the line
369− let pos = text.line_to_char(line);
404+ let pos = text.line_to_char(line);
370− Range::new(pos, pos)
405+ Range::new(pos, pos)
371− });
406+ }),
407+ );
372}
408}
373
409
374fn move_first_nonwhitespace(cx: &mut Context) {
410fn move_first_nonwhitespace(cx: &mut Context) {
375 let (view, doc) = current!(cx.editor);
411 let (view, doc) = current!(cx.editor);
412+ doc.set_selection(
413+ view.id,
414+ doc.selection(view.id).clone().transform(|range| {
415+ let text = doc.text();
416+ let line_idx = text.char_to_line(range.head);
376
417
377− let (text, selection) = doc.text_and_mut_selection(view.id);
378− selection.transform(|range| {
379− let line_idx = text.char_to_line(range.head);
380−
381− if let Some(pos) = find_first_non_whitespace_char(text.line(line_idx)) {
418+ if let Some(pos) = find_first_non_whitespace_char(text.line(line_idx)) {
382− let pos = pos + text.line_to_char(line_idx);
419+ let pos = pos + text.line_to_char(line_idx);
383− Range::new(pos, pos)
420+ Range::new(pos, pos)
384− } else {
421+ } else {
385− range
422+ range
423+ }
386− }
424+ }),
387− });
425+ );
388}
426}
389
427
390// TODO: move vs extend could take an extra type Extend/Move that would
428// TODO: move vs extend could take an extra type Extend/Move that would
@@ -395,48 +433,67 @@ fn move_next_word_start(cx: &mut Context) {
395 let count = cx.count();
433 let count = cx.count();
396 let (view, doc) = current!(cx.editor);
434 let (view, doc) = current!(cx.editor);
397
435
398− let (text, selection) = doc.text_and_mut_selection(view.id);
436+ doc.set_selection(
437+ view.id,
438+ doc.selection(view.id)
439+ .clone()
399− selection.transform(|range| movement::move_next_word_start(text, range, count));
440+ .transform(|range| movement::move_next_word_start(doc.text().slice(..), range, count)),
441+ );
400}
442}
401
443
402fn move_prev_word_start(cx: &mut Context) {
444fn move_prev_word_start(cx: &mut Context) {
403 let count = cx.count();
445 let count = cx.count();
404 let (view, doc) = current!(cx.editor);
446 let (view, doc) = current!(cx.editor);
405−
447+ doc.set_selection(
406− let (text, selection) = doc.text_and_mut_selection(view.id);
448+ view.id,
449+ doc.selection(view.id)
450+ .clone()
407− selection.transform(|range| movement::move_prev_word_start(text, range, count));
451+ .transform(|range| movement::move_prev_word_start(doc.text().slice(..), range, count)),
452+ );
408}
453}
409
454
410fn move_next_word_end(cx: &mut Context) {
455fn move_next_word_end(cx: &mut Context) {
411 let count = cx.count();
456 let count = cx.count();
412 let (view, doc) = current!(cx.editor);
457 let (view, doc) = current!(cx.editor);
413−
458+ doc.set_selection(
414− let (text, selection) = doc.text_and_mut_selection(view.id);
459+ view.id,
460+ doc.selection(view.id)
461+ .clone()
415− selection.transform(|range| movement::move_next_word_end(text, range, count));
462+ .transform(|range| movement::move_next_word_end(doc.text().slice(..), range, count)),
463+ );
416}
464}
417
465
418fn move_next_long_word_start(cx: &mut Context) {
466fn move_next_long_word_start(cx: &mut Context) {
419 let count = cx.count();
467 let count = cx.count();
420 let (view, doc) = current!(cx.editor);
468 let (view, doc) = current!(cx.editor);
421−
469+ doc.set_selection(
422− let (text, selection) = doc.text_and_mut_selection(view.id);
470+ view.id,
471+ doc.selection(view.id).clone().transform(|range| {
423− selection.transform(|range| movement::move_next_long_word_start(text, range, count));
472+ movement::move_next_long_word_start(doc.text().slice(..), range, count)
473+ }),
474+ );
424}
475}
425
476
426fn move_prev_long_word_start(cx: &mut Context) {
477fn move_prev_long_word_start(cx: &mut Context) {
427 let count = cx.count();
478 let count = cx.count();
428 let (view, doc) = current!(cx.editor);
479 let (view, doc) = current!(cx.editor);
429−
480+ doc.set_selection(
430− let (text, selection) = doc.text_and_mut_selection(view.id);
481+ view.id,
482+ doc.selection(view.id).clone().transform(|range| {
431− selection.transform(|range| movement::move_prev_long_word_start(text, range, count));
483+ movement::move_prev_long_word_start(doc.text().slice(..), range, count)
484+ }),
485+ );
432}
486}
433
487
434fn move_next_long_word_end(cx: &mut Context) {
488fn move_next_long_word_end(cx: &mut Context) {
435 let count = cx.count();
489 let count = cx.count();
436 let (view, doc) = current!(cx.editor);
490 let (view, doc) = current!(cx.editor);
437−
491+ doc.set_selection(
438− let (text, selection) = doc.text_and_mut_selection(view.id);
492+ view.id,
493+ doc.selection(view.id).clone().transform(|range| {
439− selection.transform(|range| movement::move_next_long_word_end(text, range, count));
494+ movement::move_next_long_word_end(doc.text().slice(..), range, count)
495+ }),
496+ );
440}
497}
441
498
442fn move_file_start(cx: &mut Context) {
499fn move_file_start(cx: &mut Context) {
@@ -456,37 +513,40 @@ fn move_file_end(cx: &mut Context) {
456fn extend_next_word_start(cx: &mut Context) {
513fn extend_next_word_start(cx: &mut Context) {
457 let count = cx.count();
514 let count = cx.count();
458 let (view, doc) = current!(cx.editor);
515 let (view, doc) = current!(cx.editor);
459−
516+ doc.set_selection(
460− let (text, selection) = doc.text_and_mut_selection(view.id);
517+ view.id,
461− selection.transform(|mut range| {
518+ doc.selection(view.id).clone().transform(|mut range| {
462− let word = movement::move_next_word_start(text, range, count);
519+ let word = movement::move_next_word_start(doc.text().slice(..), range, count);
463− let pos = word.head;
520+ let pos = word.head;
464− Range::new(range.anchor, pos)
521+ Range::new(range.anchor, pos)
465− });
522+ }),
523+ );
466}
524}
467
525
468fn extend_prev_word_start(cx: &mut Context) {
526fn extend_prev_word_start(cx: &mut Context) {
469 let count = cx.count();
527 let count = cx.count();
470 let (view, doc) = current!(cx.editor);
528 let (view, doc) = current!(cx.editor);
471−
529+ doc.set_selection(
472− let (text, selection) = doc.text_and_mut_selection(view.id);
530+ view.id,
473− selection.transform(|mut range| {
531+ doc.selection(view.id).clone().transform(|mut range| {
474− let word = movement::move_prev_word_start(text, range, count);
532+ let word = movement::move_prev_word_start(doc.text().slice(..), range, count);
475− let pos = word.head;
533+ let pos = word.head;
476− Range::new(range.anchor, pos)
534+ Range::new(range.anchor, pos)
477− });
535+ }),
536+ );
478}
537}
479
538
480fn extend_next_word_end(cx: &mut Context) {
539fn extend_next_word_end(cx: &mut Context) {
481 let count = cx.count();
540 let count = cx.count();
482 let (view, doc) = current!(cx.editor);
541 let (view, doc) = current!(cx.editor);
483−
542+ doc.set_selection(
484− let (text, selection) = doc.text_and_mut_selection(view.id);
543+ view.id,
485− selection.transform(|mut range| {
544+ doc.selection(view.id).clone().transform(|mut range| {
486− let word = movement::move_next_word_end(text, range, count);
545+ let word = movement::move_next_word_end(doc.text().slice(..), range, count);
487− let pos = word.head;
546+ let pos = word.head;
488− Range::new(range.anchor, pos)
547+ Range::new(range.anchor, pos)
489− });
548+ }),
549+ );
490}
550}
491
551
492#[inline]
552#[inline]
@@ -530,18 +590,23 @@ where
530
590
531 let (view, doc) = current!(cx.editor);
591 let (view, doc) = current!(cx.editor);
532
592
533− let (text, selection) = doc.text_and_mut_selection(view.id);
593+ doc.set_selection(
594+ view.id,
534− selection.transform(|mut range| {
595+ doc.selection(view.id).clone().transform(|mut range| {
535− search_fn(text, ch, range.head, count, inclusive).map_or(range, |pos| {
596+ search_fn(doc.text().slice(..), ch, range.head, count, inclusive).map_or(
597+ range,
598+ |pos| {
536− if extend {
599+ if extend {
537− Range::new(range.anchor, pos)
600+ Range::new(range.anchor, pos)
538− } else {
601+ } else {
539− // select
602+ // select
540− Range::new(range.head, pos)
603+ Range::new(range.head, pos)
541− }
604+ }
542− // or (pos, pos) to move to found val
605+ // or (pos, pos) to move to found val
606+ },
607+ )
543− })
608+ }),
544− });
609+ );
545 })
610 })
546}
611}
547
612
@@ -619,18 +684,20 @@ fn extend_prev_char(cx: &mut Context) {
619
684
620fn extend_first_nonwhitespace(cx: &mut Context) {
685fn extend_first_nonwhitespace(cx: &mut Context) {
621 let (view, doc) = current!(cx.editor);
686 let (view, doc) = current!(cx.editor);
687+ doc.set_selection(
688+ view.id,
689+ doc.selection(view.id).clone().transform(|range| {
690+ let text = doc.text();
691+ let line_idx = text.char_to_line(range.head);
622
692
623− let (text, selection) = doc.text_and_mut_selection(view.id);
624− selection.transform(|range| {
625− let line_idx = text.char_to_line(range.head);
626−
627− if let Some(pos) = find_first_non_whitespace_char(text.line(line_idx)) {
693+ if let Some(pos) = find_first_non_whitespace_char(text.line(line_idx)) {
628− let pos = pos + text.line_to_char(line_idx);
694+ let pos = pos + text.line_to_char(line_idx);
629− Range::new(range.anchor, pos)
695+ Range::new(range.anchor, pos)
630− } else {
696+ } else {
631− range
697+ range
698+ }
632− }
699+ }),
633− });
700+ );
634}
701}
635
702
636fn replace(cx: &mut Context) {
703fn replace(cx: &mut Context) {
@@ -741,65 +808,101 @@ fn half_page_down(cx: &mut Context) {
741fn extend_char_left(cx: &mut Context) {
808fn extend_char_left(cx: &mut Context) {
742 let count = cx.count();
809 let count = cx.count();
743 let (view, doc) = current!(cx.editor);
810 let (view, doc) = current!(cx.editor);
744− let (text, selection) = doc.text_and_mut_selection(view.id);
811+ doc.set_selection(
812+ view.id,
745− selection.transform(|range| {
813+ doc.selection(view.id).clone().transform(|range| {
746− movement::move_horizontally(text, range, Direction::Backward, count, Movement::Extend)
814+ movement::move_horizontally(
815+ doc.text().slice(..),
816+ range,
817+ Direction::Backward,
818+ count,
819+ Movement::Extend,
820+ )
747− });
821+ }),
822+ );
748}
823}
749
824
750fn extend_char_right(cx: &mut Context) {
825fn extend_char_right(cx: &mut Context) {
751 let count = cx.count();
826 let count = cx.count();
752 let (view, doc) = current!(cx.editor);
827 let (view, doc) = current!(cx.editor);
753− let (text, selection) = doc.text_and_mut_selection(view.id);
828+ doc.set_selection(
829+ view.id,
754− selection.transform(|range| {
830+ doc.selection(view.id).clone().transform(|range| {
755− movement::move_horizontally(text, range, Direction::Forward, count, Movement::Extend)
831+ movement::move_horizontally(
832+ doc.text().slice(..),
833+ range,
834+ Direction::Forward,
835+ count,
836+ Movement::Extend,
837+ )
756− });
838+ }),
839+ );
757}
840}
758
841
759fn extend_line_up(cx: &mut Context) {
842fn extend_line_up(cx: &mut Context) {
760 let count = cx.count();
843 let count = cx.count();
761 let (view, doc) = current!(cx.editor);
844 let (view, doc) = current!(cx.editor);
762− let (text, selection) = doc.text_and_mut_selection(view.id);
845+ doc.set_selection(
846+ view.id,
763− selection.transform(|range| {
847+ doc.selection(view.id).clone().transform(|range| {
764− movement::move_vertically(text, range, Direction::Backward, count, Movement::Extend)
848+ movement::move_vertically(
849+ doc.text().slice(..),
850+ range,
851+ Direction::Backward,
852+ count,
853+ Movement::Extend,
854+ )
765− });
855+ }),
856+ );
766}
857}
767
858
768fn extend_line_down(cx: &mut Context) {
859fn extend_line_down(cx: &mut Context) {
769 let count = cx.count();
860 let count = cx.count();
770 let (view, doc) = current!(cx.editor);
861 let (view, doc) = current!(cx.editor);
771− let (text, selection) = doc.text_and_mut_selection(view.id);
862+ doc.set_selection(
863+ view.id,
772− selection.transform(|range| {
864+ doc.selection(view.id).clone().transform(|range| {
773− movement::move_vertically(text, range, Direction::Forward, count, Movement::Extend)
865+ movement::move_vertically(
866+ doc.text().slice(..),
867+ range,
868+ Direction::Forward,
869+ count,
870+ Movement::Extend,
871+ )
774− });
872+ }),
873+ );
775}
874}
776
875
777fn extend_line_end(cx: &mut Context) {
876fn extend_line_end(cx: &mut Context) {
778 let (view, doc) = current!(cx.editor);
877 let (view, doc) = current!(cx.editor);
878+ doc.set_selection(
879+ view.id,
880+ doc.selection(view.id).clone().transform(|range| {
881+ let text = doc.text().slice(..);
882+ let line = text.char_to_line(range.head);
779
883
780− let (text, selection) = doc.text_and_mut_selection(view.id);
781− selection.transform(|range| {
782− let line = text.char_to_line(range.head);
783−
784− let pos = line_end_char_index(&text.slice(..), line);
884+ let pos = line_end_char_index(&text, line);
785− let pos = graphemes::nth_prev_grapheme_boundary(text.slice(..), pos, 1);
885+ let pos = graphemes::nth_prev_grapheme_boundary(text, pos, 1);
786− let pos = range.head.max(pos).max(text.line_to_char(line));
886+ let pos = range.head.max(pos).max(text.line_to_char(line));
787
887
788− Range::new(range.anchor, pos)
888+ Range::new(range.anchor, pos)
789− });
889+ }),
890+ );
790}
891}
791
892
792fn extend_line_start(cx: &mut Context) {
893fn extend_line_start(cx: &mut Context) {
793 let (view, doc) = current!(cx.editor);
894 let (view, doc) = current!(cx.editor);
895+ doc.set_selection(
896+ view.id,
897+ doc.selection(view.id).clone().transform(|range| {
898+ let text = doc.text();
899+ let line = text.char_to_line(range.head);
794
900
795− let (text, selection) = doc.text_and_mut_selection(view.id);
796− selection.transform(|range| {
797− let line = text.char_to_line(range.head);
798−
799− // adjust to start of the line
901+ // adjust to start of the line
800− let pos = text.line_to_char(line);
902+ let pos = text.line_to_char(line);
801− Range::new(range.anchor, pos)
903+ Range::new(range.anchor, pos)
802− });
904+ }),
905+ );
803}
906}
804
907
805fn select_all(cx: &mut Context) {
908fn select_all(cx: &mut Context) {
@@ -993,15 +1096,23 @@ fn change_selection(cx: &mut Context) {
993fn collapse_selection(cx: &mut Context) {
1096fn collapse_selection(cx: &mut Context) {
994 let (view, doc) = current!(cx.editor);
1097 let (view, doc) = current!(cx.editor);
995
1098
996− doc.selection_mut(view.id)
1099+ doc.set_selection(
1100+ view.id,
1101+ doc.selection(view.id)
1102+ .clone()
997− .transform(|range| Range::new(range.head, range.head));
1103+ .transform(|range| Range::new(range.head, range.head)),
1104+ );
998}
1105}
999
1106
1000fn flip_selections(cx: &mut Context) {
1107fn flip_selections(cx: &mut Context) {
1001 let (view, doc) = current!(cx.editor);
1108 let (view, doc) = current!(cx.editor);
1002
1109
1003− doc.selection_mut(view.id)
1110+ doc.set_selection(
1111+ view.id,
1112+ doc.selection(view.id)
1113+ .clone()
1004− .transform(|range| Range::new(range.head, range.anchor));
1114+ .transform(|range| Range::new(range.head, range.anchor)),
1115+ );
1005}
1116}
1006
1117
1007fn enter_insert_mode(doc: &mut Document) {
1118fn enter_insert_mode(doc: &mut Document) {
@@ -1013,8 +1124,12 @@ fn insert_mode(cx: &mut Context) {
1013 let (view, doc) = current!(cx.editor);
1124 let (view, doc) = current!(cx.editor);
1014 enter_insert_mode(doc);
1125 enter_insert_mode(doc);
1015
1126
1016− doc.selection_mut(view.id)
1127+ doc.set_selection(
1128+ view.id,
1129+ doc.selection(view.id)
1130+ .clone()
1017− .transform(|range| Range::new(range.to(), range.from()));
1131+ .transform(|range| Range::new(range.to(), range.from())),
1132+ );
1018}
1133}
1019
1134
1020// inserts at the end of each selection
1135// inserts at the end of each selection
@@ -1023,15 +1138,14 @@ fn append_mode(cx: &mut Context) {
1023 enter_insert_mode(doc);
1138 enter_insert_mode(doc);
1024 doc.restore_cursor = true;
1139 doc.restore_cursor = true;
1025
1140
1026− let (text, selection) = doc.text_and_mut_selection(view.id);
1141+ let selection = doc.selection(view.id).clone().transform(|range| {
1027− selection.transform(|range| {
1028 Range::new(
1142 Range::new(
1029 range.from(),
1143 range.from(),
1030− graphemes::next_grapheme_boundary(text, range.to()), // to() + next char
1144+ graphemes::next_grapheme_boundary(doc.text().slice(..), range.to()), // to() + next char
1031 )
1145 )
1032 });
1146 });
1033
1147
1034− let end = text.len_chars();
1148+ let end = doc.text().len_chars();
1035
1149
1036 if selection.iter().any(|range| range.head == end) {
1150 if selection.iter().any(|range| range.head == end) {
1037 let transaction = Transaction::change(
1151 let transaction = Transaction::change(
@@ -1040,6 +1154,8 @@ fn append_mode(cx: &mut Context) {
1040 );
1154 );
1041 doc.apply(&transaction, view.id);
1155 doc.apply(&transaction, view.id);
1042 }
1156 }
1157+
1158+ doc.set_selection(view.id, selection);
1043}
1159}
1044
1160
1045mod cmd {
1161mod cmd {
@@ -1845,12 +1961,15 @@ fn append_to_line(cx: &mut Context) {
1845 let (view, doc) = current!(cx.editor);
1961 let (view, doc) = current!(cx.editor);
1846 enter_insert_mode(doc);
1962 enter_insert_mode(doc);
1847
1963
1848− let (text, selection) = doc.text_and_mut_selection(view.id);
1964+ doc.set_selection(
1965+ view.id,
1849− selection.transform(|range| {
1966+ doc.selection(view.id).clone().transform(|range| {
1967+ let text = &doc.text().slice(..);
1850− let line = text.char_to_line(range.head);
1968+ let line = text.char_to_line(range.head);
1851− let pos = line_end_char_index(&text.slice(..), line);
1969+ let pos = line_end_char_index(text, line);
1852− Range::new(pos, pos)
1970+ Range::new(pos, pos)
1853− });
1971+ }),
1972+ );
1854}
1973}
1855
1974
1856/// Sometimes when applying formatting changes we want to mark the buffer as unmodified, for
1975/// Sometimes when applying formatting changes we want to mark the buffer as unmodified, for
@@ -1980,13 +2099,15 @@ fn normal_mode(cx: &mut Context) {
1980
2099
1981 // if leaving append mode, move cursor back by 1
2100 // if leaving append mode, move cursor back by 1
1982 if doc.restore_cursor {
2101 if doc.restore_cursor {
1983− let (text, selection) = doc.text_and_mut_selection(view.id);
2102+ doc.set_selection(
2103+ view.id,
1984− selection.transform(|range| {
2104+ doc.selection(view.id).clone().transform(|range| {
1985− Range::new(
2105+ Range::new(
1986− range.from(),
2106+ range.from(),
1987− graphemes::prev_grapheme_boundary(text, range.to()),
2107+ graphemes::prev_grapheme_boundary(doc.text().slice(..), range.to()),
1988− )
2108+ )
1989− });
2109+ }),
2110+ );
1990
2111
1991 doc.restore_cursor = false;
2112 doc.restore_cursor = false;
1992 }
2113 }
@@ -2619,8 +2740,12 @@ pub mod insert {
2619 let count = cx.count();
2740 let count = cx.count();
2620 let (view, doc) = current!(cx.editor);
2741 let (view, doc) = current!(cx.editor);
2621
2742
2622− let (text, selection) = doc.text_and_mut_selection(view.id);
2743+ doc.set_selection(
2744+ view.id,
2745+ doc.selection(view.id).clone().transform(|range| {
2623− selection.transform(|range| movement::move_prev_word_start(text, range, count));
2746+ movement::move_prev_word_start(doc.text().slice(..), range, count)
2747+ }),
2748+ );
2624 delete_selection(cx)
2749 delete_selection(cx)
2625 }
2750 }
2626}
2751}
helix-view/src/document.rs+2−18
@@ -13,8 +13,8 @@ use helix_core::{
13 history::History,
13 history::History,
14 line_ending::auto_detect_line_ending,
14 line_ending::auto_detect_line_ending,
15 syntax::{self, LanguageConfiguration},
15 syntax::{self, LanguageConfiguration},
16− ChangeSet, Diagnostic, LineEnding, Rope, RopeBuilder, RopeSlice, Selection, State, Syntax,
16+ ChangeSet, Diagnostic, LineEnding, Rope, RopeBuilder, Selection, State, Syntax, Transaction,
17− Transaction, DEFAULT_LINE_ENDING,
17+ DEFAULT_LINE_ENDING,
18};
18};
19use helix_lsp::util::LspFormatting;
19use helix_lsp::util::LspFormatting;
20
20
@@ -1000,22 +1000,6 @@ impl Document {
1000 &self.selections[&view_id]
1000 &self.selections[&view_id]
1001 }
1001 }
1002
1002
1003− #[inline]
1004− pub fn selection_mut(&mut self, view_id: ViewId) -> &mut Selection {
1005− self.selections
1006− .get_mut(&view_id)
1007− .expect("No selection set with the given ViewId")
1008− }
1009−
1010− pub fn text_and_mut_selection(&mut self, view_id: ViewId) -> (RopeSlice, &mut Selection) {
1011− (
1012− self.text.slice(..),
1013− self.selections
1014− .get_mut(&view_id)
1015− .expect("No selection set with the given ViewId"),
1016− )
1017− }
1018−
1019 pub fn relative_path(&self) -> Option<PathBuf> {
1003 pub fn relative_path(&self) -> Option<PathBuf> {
1020 let cwdir = std::env::current_dir().expect("couldn't determine current directory");
1004 let cwdir = std::env::current_dir().expect("couldn't determine current directory");
1021
1005