@@ -373,15 +373,16 @@ fn goto_line_end(cx: &mut Context) {
374 let selection = doc.selection(view.id).clone().transform(|range| {
374 let selection = doc.selection(view.id).clone().transform(|range| {
375 let line = range.head_line(text);
375 let line = range.head_line(text);
376+ let line_start = text.line_to_char(line);
377− let mut pos = line_end_char_index(&text, line);
378+ let pos = graphemes::prev_grapheme_boundary(text, line_end_char_index(&text, line))
378− if doc.mode != Mode::Select {
379+ .max(line_start);
379− pos = graphemes::prev_grapheme_boundary(text, pos);
382− pos = range.head.max(pos).max(text.line_to_char(line));
384− range.put(text, pos, doc.mode == Mode::Select)
381+ if doc.mode == Mode::Select {
382+ range.move_head(text, pos, true)
386 doc.set_selection(view.id, selection);
387 doc.set_selection(view.id, selection);
@@ -392,12 +393,13 @@ fn goto_line_end_newline(cx: &mut Context) {
393 let selection = doc.selection(view.id).clone().transform(|range| {
394 let selection = doc.selection(view.id).clone().transform(|range| {
394 let line = range.head_line(text);
395 let line = range.head_line(text);
396+ let pos = line_end_char_index(&text, line);
396− let mut pos = text.line_to_char((line + 1).min(text.len_lines()));
397− if doc.mode != Mode::Select {
398+ if doc.mode == Mode::Select {
398− pos = graphemes::prev_grapheme_boundary(text, pos);
399+ range.move_head(text, pos, true)
400− range.put(text, pos, doc.mode == Mode::Select)
402 doc.set_selection(view.id, selection);
404 doc.set_selection(view.id, selection);
@@ -411,7 +413,11 @@ fn goto_line_start(cx: &mut Context) {
412 // adjust to start of the line
414 // adjust to start of the line
413 let pos = text.line_to_char(line);
415 let pos = text.line_to_char(line);
414− range.put(text, pos, doc.mode == Mode::Select)
416+ if doc.mode == Mode::Select {
417+ range.move_head(text, pos, true)
416 doc.set_selection(view.id, selection);
422 doc.set_selection(view.id, selection);
@@ -425,7 +431,11 @@ fn goto_first_nonwhitespace(cx: &mut Context) {
426 if let Some(pos) = find_first_non_whitespace_char(text.line(line)) {
432 if let Some(pos) = find_first_non_whitespace_char(text.line(line)) {
427 let pos = pos + text.line_to_char(line);
433 let pos = pos + text.line_to_char(line);
428− range.put(text, pos, doc.mode == Mode::Select)
434+ if doc.mode == Mode::Select {
435+ range.move_head(text, pos, true)
@@ -569,8 +579,8 @@ fn extend_next_word_start(cx: &mut Context) {
569 .min_width_1(text)
579 .min_width_1(text)
570 .transform(|range| {
580 .transform(|range| {
571 let word = movement::move_next_word_start(text, range, count);
581 let word = movement::move_next_word_start(text, range, count);
572− let pos = word.head;
582+ let pos = graphemes::prev_grapheme_boundary(text, word.head);
573− range.put(text, pos, true)
583+ range.move_head(text, pos, true)
575 doc.set_selection(view.id, selection);
585 doc.set_selection(view.id, selection);
@@ -587,7 +597,7 @@ fn extend_prev_word_start(cx: &mut Context) {
587 .transform(|range| {
597 .transform(|range| {
588 let word = movement::move_prev_word_start(text, range, count);
598 let word = movement::move_prev_word_start(text, range, count);
589 let pos = word.head;
599 let pos = word.head;
590− range.put(text, pos, true)
600+ range.move_head(text, pos, true)
592 doc.set_selection(view.id, selection);
602 doc.set_selection(view.id, selection);
@@ -603,8 +613,8 @@ fn extend_next_word_end(cx: &mut Context) {
603 .min_width_1(text)
613 .min_width_1(text)
604 .transform(|range| {
614 .transform(|range| {
605 let word = movement::move_next_word_end(text, range, count);
615 let word = movement::move_next_word_end(text, range, count);
606− let pos = word.head;
616+ let pos = graphemes::prev_grapheme_boundary(text, word.head);
607− range.put(text, pos, true)
617+ range.move_head(text, pos, true)
609 doc.set_selection(view.id, selection);
619 doc.set_selection(view.id, selection);
@@ -652,11 +662,17 @@ where
652 let text = doc.text().slice(..);
662 let text = doc.text().slice(..);
654 let selection = doc.selection(view.id).clone().transform(|range| {
664 let selection = doc.selection(view.id).clone().transform(|range| {
665+ let range = if range.anchor < range.head {
666+ // For 1-width cursor semantics.
667+ Range::new(range.anchor, range.head - 1)
655 search_fn(text, ch, range.head, count, inclusive).map_or(range, |pos| {
671 search_fn(text, ch, range.head, count, inclusive).map_or(range, |pos| {
656 if extend {
672 if extend {
657− range.put(text, pos, true)
673+ range.move_head(text, pos, true)
659− range.put(text, pos.saturating_sub(1), false)
675+ Range::point(pos)
@@ -664,10 +680,39 @@ where
683+fn find_next_char_impl(
690+ let pos = (pos + 1).min(text.len_chars());
692+ search::find_nth_next(text, ch, pos, n)
694+ search::find_nth_next(text, ch, pos, n).map(|n| n.saturating_sub(1))
698+fn find_prev_char_impl(
706+ search::find_nth_prev(text, ch, pos, n)
708+ search::find_nth_prev(text, ch, pos, n).map(|n| (n + 1).min(text.len_chars()))
667fn find_till_char(cx: &mut Context) {
712fn find_till_char(cx: &mut Context) {
668 find_char_impl(
713 find_char_impl(
670− search::find_nth_next,
715+ find_next_char_impl,
671 false, /* inclusive */
716 false, /* inclusive */
672 false, /* extend */
717 false, /* extend */
@@ -676,7 +721,7 @@ fn find_till_char(cx: &mut Context) {
676fn find_next_char(cx: &mut Context) {
721fn find_next_char(cx: &mut Context) {
677 find_char_impl(
722 find_char_impl(
679− search::find_nth_next,
724+ find_next_char_impl,
680 true, /* inclusive */
725 true, /* inclusive */
681 false, /* extend */
726 false, /* extend */
@@ -685,7 +730,7 @@ fn find_next_char(cx: &mut Context) {
685fn extend_till_char(cx: &mut Context) {
730fn extend_till_char(cx: &mut Context) {
686 find_char_impl(
731 find_char_impl(
688− search::find_nth_next,
733+ find_next_char_impl,
689 false, /* inclusive */
734 false, /* inclusive */
690 true, /* extend */
735 true, /* extend */
@@ -694,7 +739,7 @@ fn extend_till_char(cx: &mut Context) {
694fn extend_next_char(cx: &mut Context) {
739fn extend_next_char(cx: &mut Context) {
695 find_char_impl(
740 find_char_impl(
697− search::find_nth_next,
742+ find_next_char_impl,
698 true, /* inclusive */
743 true, /* inclusive */
699 true, /* extend */
744 true, /* extend */
@@ -703,7 +748,7 @@ fn extend_next_char(cx: &mut Context) {
703fn till_prev_char(cx: &mut Context) {
748fn till_prev_char(cx: &mut Context) {
704 find_char_impl(
749 find_char_impl(
706− search::find_nth_prev,
751+ find_prev_char_impl,
707 false, /* inclusive */
752 false, /* inclusive */
708 false, /* extend */
753 false, /* extend */
@@ -712,7 +757,7 @@ fn till_prev_char(cx: &mut Context) {
712fn find_prev_char(cx: &mut Context) {
757fn find_prev_char(cx: &mut Context) {
713 find_char_impl(
758 find_char_impl(
715− search::find_nth_prev,
760+ find_prev_char_impl,
716 true, /* inclusive */
761 true, /* inclusive */
717 false, /* extend */
762 false, /* extend */
@@ -721,7 +766,7 @@ fn find_prev_char(cx: &mut Context) {
721fn extend_till_prev_char(cx: &mut Context) {
766fn extend_till_prev_char(cx: &mut Context) {
722 find_char_impl(
767 find_char_impl(
724− search::find_nth_prev,
769+ find_prev_char_impl,
725 false, /* inclusive */
770 false, /* inclusive */
726 true, /* extend */
771 true, /* extend */
@@ -730,7 +775,7 @@ fn extend_till_prev_char(cx: &mut Context) {
730fn extend_prev_char(cx: &mut Context) {
775fn extend_prev_char(cx: &mut Context) {
731 find_char_impl(
776 find_char_impl(
733− search::find_nth_prev,
778+ find_prev_char_impl,
734 true, /* inclusive */
779 true, /* inclusive */
735 true, /* extend */
780 true, /* extend */