@@ -1041,7 +1041,25 @@ fn split_selection_on_newline(cx: &mut Context) {
10411041fn search_impl(doc: &mut Document, view: &mut View, contents: &str, regex: &Regex, extend: bool) {
10421042 let text = doc.text();
10431043 let selection = doc.selection(view.id);
1044− let start = text.char_to_byte(selection.cursor(text.slice(..)));
1044+ let start = {
1045+ let range = selection.primary();
1046+
1047+ // This is a little bit weird. Due to 1-width cursor semantics, we
1048+ // would typically want the search to always begin at the visual left-side
1049+ // of the head. However, when there's already a selection from e.g. a
1050+ // previous search result, we don't want to include any of that selection
1051+ // in the subsequent search. The code below makes a compromise between the
1052+ // two behaviors that hopefully behaves the way most people expect most of
1053+ // the time.
1054+ if range.anchor <= range.head {
1055+ text.char_to_byte(range.head)
1056+ } else {
1057+ text.char_to_byte(graphemes::next_grapheme_boundary(
1058+ text.slice(..),
1059+ range.head,
1060+ ))
1061+ }
1062+ };
10451063
10461064 // use find_at to find the next match after the cursor, loop around the end
10471065 // Careful, `Regex` uses `bytes` as offsets, not character indices!