commit dc05598d0201d156e8ac435f156751e7f6b224ae
parent 66e4784f5acef73ede2b1182b2e6d5a99f44f64a
Author: luukvbaal <luukvbaal@gmail.com>
Date: Thu, 12 Jun 2025 08:53:10 +0200
fix(cmdline): set search cursor after ui_flush() (#34418)
Problem: vim.ui_attach cmdline events emitted with an ephemeral cursor
position that is only used as the start of the search.
Solution: Delay setting the cursor position until after ui_flush().
Diffstat:
1 file changed, 26 insertions(+), 35 deletions(-)
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
@@ -421,7 +421,6 @@ theend:
// May do 'incsearch' highlighting if desired.
static void may_do_incsearch_highlighting(int firstc, int count, incsearch_state_T *s)
{
- pos_T end_pos;
int skiplen, patlen;
int search_delim;
@@ -429,8 +428,7 @@ static void may_do_incsearch_highlighting(int firstc, int count, incsearch_state
// NOTE: must call restore_last_search_pattern() before returning!
save_last_search_pattern();
- if (!do_incsearch_highlighting(firstc, &search_delim, s, &skiplen,
- &patlen)) {
+ if (!do_incsearch_highlighting(firstc, &search_delim, s, &skiplen, &patlen)) {
restore_last_search_pattern();
finish_incsearch_highlighting(false, s, true);
return;
@@ -444,6 +442,16 @@ static void may_do_incsearch_highlighting(int firstc, int count, incsearch_state
}
s->incsearch_postponed = false;
+ // Use the previous pattern for ":s//".
+ char next_char = ccline.cmdbuff[skiplen + patlen];
+ bool use_last_pat = patlen == 0 && skiplen > 0
+ && ccline.cmdbuff[skiplen - 1] == next_char;
+
+ if (patlen != 0 || use_last_pat) {
+ ui_busy_start();
+ ui_flush();
+ }
+
if (search_first_line == 0) {
// start at the original cursor position
curwin->w_cursor = s->search_start;
@@ -456,40 +464,27 @@ static void may_do_incsearch_highlighting(int firstc, int count, incsearch_state
curwin->w_cursor.lnum = search_first_line;
curwin->w_cursor.col = 0;
}
- int found; // do_search() result
- // Use the previous pattern for ":s//".
- char next_char = ccline.cmdbuff[skiplen + patlen];
- bool use_last_pat = patlen == 0 && skiplen > 0
- && ccline.cmdbuff[skiplen - 1] == next_char;
+ int found = 0; // do_search() result
- // If there is no pattern, don't do anything.
- if (patlen == 0 && !use_last_pat) {
- found = 0;
- set_no_hlsearch(true); // turn off previous highlight
- redraw_all_later(UPD_SOME_VALID);
- } else {
+ if (patlen != 0 || use_last_pat) {
int search_flags = SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK;
- ui_busy_start();
- ui_flush();
- emsg_off++; // So it doesn't beep if bad expr
- // Set the time limit to half a second.
- proftime_T tm = profile_setlimit(500);
if (!p_hls) {
search_flags += SEARCH_KEEP;
}
if (search_first_line != 0) {
search_flags += SEARCH_START;
}
+ // Set the time limit to half a second.
+ proftime_T tm = profile_setlimit(500);
+ searchit_arg_T sia = { .sa_tm = &tm };
ccline.cmdbuff[skiplen + patlen] = NUL;
- searchit_arg_T sia = {
- .sa_tm = &tm,
- };
+ emsg_off++; // So it doesn't beep if bad expr
found = do_search(NULL, firstc == ':' ? '/' : firstc, search_delim,
ccline.cmdbuff + skiplen, (size_t)patlen, count,
search_flags, &sia);
- ccline.cmdbuff[skiplen + patlen] = next_char;
emsg_off--;
+ ccline.cmdbuff[skiplen + patlen] = next_char;
if (curwin->w_cursor.lnum < search_first_line
|| curwin->w_cursor.lnum > search_last_line) {
// match outside of address range
@@ -507,31 +502,27 @@ static void may_do_incsearch_highlighting(int firstc, int count, incsearch_state
s->incsearch_postponed = true;
}
ui_busy_stop();
- }
-
- if (found != 0) {
- highlight_match = true; // highlight position
} else {
- highlight_match = false; // remove highlight
+ set_no_hlsearch(true); // turn off previous highlight
+ redraw_all_later(UPD_SOME_VALID);
}
+ highlight_match = found != 0; // add or remove search match position
+
// first restore the old curwin values, so the screen is
// positioned in the same way as the actual search command
restore_viewstate(curwin, &s->old_viewstate);
changed_cline_bef_curs(curwin);
update_topline(curwin);
+ pos_T end_pos = curwin->w_cursor;
if (found != 0) {
- pos_T save_pos = curwin->w_cursor;
-
s->match_start = curwin->w_cursor;
set_search_match(&curwin->w_cursor);
validate_cursor(curwin);
- end_pos = curwin->w_cursor;
- s->match_end = end_pos;
- curwin->w_cursor = save_pos;
- } else {
- end_pos = curwin->w_cursor; // shutup gcc 4
+ s->match_end = curwin->w_cursor;
+ curwin->w_cursor = end_pos;
+ end_pos = s->match_end;
}
// Disable 'hlsearch' highlighting if the pattern matches