mirror of
https://github.com/neovim/neovim
synced 2025-07-27 17:02:14 +00:00
fix(substitute): properly check if preview is needed (#23809)
This commit is contained in:
@ -3280,9 +3280,11 @@ static int check_regexp_delim(int c)
|
|||||||
///
|
///
|
||||||
/// The usual escapes are supported as described in the regexp docs.
|
/// The usual escapes are supported as described in the regexp docs.
|
||||||
///
|
///
|
||||||
/// @param do_buf_event If `true`, send buffer updates.
|
/// @param cmdpreview_ns The namespace to show 'inccommand' preview highlights.
|
||||||
|
/// If <= 0, preview shouldn't be shown.
|
||||||
/// @return 0, 1 or 2. See show_cmdpreview() for more information on what the return value means.
|
/// @return 0, 1 or 2. See show_cmdpreview() for more information on what the return value means.
|
||||||
static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T cmdpreview_bufnr)
|
static int do_sub(exarg_T *eap, const proftime_T timeout, const long cmdpreview_ns,
|
||||||
|
const handle_T cmdpreview_bufnr)
|
||||||
{
|
{
|
||||||
#define ADJUST_SUB_FIRSTLNUM() \
|
#define ADJUST_SUB_FIRSTLNUM() \
|
||||||
do { \
|
do { \
|
||||||
@ -3400,7 +3402,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
|
|||||||
MB_PTR_ADV(cmd);
|
MB_PTR_ADV(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!eap->skip && !cmdpreview) {
|
if (!eap->skip && cmdpreview_ns <= 0) {
|
||||||
sub_set_replacement((SubReplacementString) {
|
sub_set_replacement((SubReplacementString) {
|
||||||
.sub = xstrdup(sub),
|
.sub = xstrdup(sub),
|
||||||
.timestamp = os_time(),
|
.timestamp = os_time(),
|
||||||
@ -3420,7 +3422,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
|
|||||||
endcolumn = (curwin->w_curswant == MAXCOL);
|
endcolumn = (curwin->w_curswant == MAXCOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sub != NULL && sub_joining_lines(eap, pat, sub, cmd, !cmdpreview)) {
|
if (sub != NULL && sub_joining_lines(eap, pat, sub, cmd, cmdpreview_ns <= 0)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3465,7 +3467,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (search_regcomp(pat, NULL, RE_SUBST, which_pat,
|
if (search_regcomp(pat, NULL, RE_SUBST, which_pat,
|
||||||
(cmdpreview ? 0 : SEARCH_HIS), ®match) == FAIL) {
|
(cmdpreview_ns > 0 ? 0 : SEARCH_HIS), ®match) == FAIL) {
|
||||||
if (subflags.do_error) {
|
if (subflags.do_error) {
|
||||||
emsg(_(e_invcmd));
|
emsg(_(e_invcmd));
|
||||||
}
|
}
|
||||||
@ -3494,7 +3496,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
|
|||||||
sub = xstrdup(sub);
|
sub = xstrdup(sub);
|
||||||
sub_copy = sub;
|
sub_copy = sub;
|
||||||
} else {
|
} else {
|
||||||
char *newsub = regtilde(sub, magic_isset(), cmdpreview);
|
char *newsub = regtilde(sub, magic_isset(), cmdpreview_ns > 0);
|
||||||
if (newsub != sub) {
|
if (newsub != sub) {
|
||||||
// newsub was allocated, free it later.
|
// newsub was allocated, free it later.
|
||||||
sub_copy = newsub;
|
sub_copy = newsub;
|
||||||
@ -3508,7 +3510,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
|
|||||||
|
|
||||||
for (linenr_T lnum = eap->line1;
|
for (linenr_T lnum = eap->line1;
|
||||||
lnum <= line2 && !got_quit && !aborting()
|
lnum <= line2 && !got_quit && !aborting()
|
||||||
&& (!cmdpreview || preview_lines.lines_needed <= (linenr_T)p_cwh
|
&& (cmdpreview_ns <= 0 || preview_lines.lines_needed <= (linenr_T)p_cwh
|
||||||
|| lnum <= curwin->w_botline);
|
|| lnum <= curwin->w_botline);
|
||||||
lnum++) {
|
lnum++) {
|
||||||
long nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum,
|
long nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum,
|
||||||
@ -3669,7 +3671,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subflags.do_ask && !cmdpreview) {
|
if (subflags.do_ask && cmdpreview_ns <= 0) {
|
||||||
int typed = 0;
|
int typed = 0;
|
||||||
|
|
||||||
// change State to MODE_CONFIRM, so that the mouse works
|
// change State to MODE_CONFIRM, so that the mouse works
|
||||||
@ -3882,7 +3884,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
|
|||||||
// Save the line numbers for the preview buffer
|
// Save the line numbers for the preview buffer
|
||||||
// NOTE: If the pattern matches a final newline, the next line will
|
// NOTE: If the pattern matches a final newline, the next line will
|
||||||
// be shown also, but should not be highlighted. Intentional for now.
|
// be shown also, but should not be highlighted. Intentional for now.
|
||||||
if (cmdpreview && !has_second_delim) {
|
if (cmdpreview_ns > 0 && !has_second_delim) {
|
||||||
current_match.start.col = regmatch.startpos[0].col;
|
current_match.start.col = regmatch.startpos[0].col;
|
||||||
if (current_match.end.lnum == 0) {
|
if (current_match.end.lnum == 0) {
|
||||||
current_match.end.lnum = sub_firstlnum + (linenr_T)nmatch - 1;
|
current_match.end.lnum = sub_firstlnum + (linenr_T)nmatch - 1;
|
||||||
@ -3897,7 +3899,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
|
|||||||
|
|
||||||
// 3. Substitute the string. During 'inccommand' preview only do this if
|
// 3. Substitute the string. During 'inccommand' preview only do this if
|
||||||
// there is a replace pattern.
|
// there is a replace pattern.
|
||||||
if (!cmdpreview || has_second_delim) {
|
if (cmdpreview_ns <= 0 || has_second_delim) {
|
||||||
long lnum_start = lnum; // save the start lnum
|
long lnum_start = lnum; // save the start lnum
|
||||||
int save_ma = curbuf->b_p_ma;
|
int save_ma = curbuf->b_p_ma;
|
||||||
int save_sandbox = sandbox;
|
int save_sandbox = sandbox;
|
||||||
@ -4147,7 +4149,7 @@ skip:
|
|||||||
|
|
||||||
#define PUSH_PREVIEW_LINES() \
|
#define PUSH_PREVIEW_LINES() \
|
||||||
do { \
|
do { \
|
||||||
if (cmdpreview) { \
|
if (cmdpreview_ns > 0) { \
|
||||||
linenr_T match_lines = current_match.end.lnum \
|
linenr_T match_lines = current_match.end.lnum \
|
||||||
- current_match.start.lnum +1; \
|
- current_match.start.lnum +1; \
|
||||||
if (preview_lines.subresults.size > 0) { \
|
if (preview_lines.subresults.size > 0) { \
|
||||||
@ -4230,7 +4232,7 @@ skip:
|
|||||||
beginline(BL_WHITE | BL_FIX);
|
beginline(BL_WHITE | BL_FIX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!cmdpreview && !do_sub_msg(subflags.do_count) && subflags.do_ask && p_ch > 0) {
|
if (cmdpreview_ns <= 0 && !do_sub_msg(subflags.do_count) && subflags.do_ask && p_ch > 0) {
|
||||||
msg("");
|
msg("");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -4269,7 +4271,7 @@ skip:
|
|||||||
int retv = 0;
|
int retv = 0;
|
||||||
|
|
||||||
// Show 'inccommand' preview if there are matched lines.
|
// Show 'inccommand' preview if there are matched lines.
|
||||||
if (cmdpreview && !aborting()) {
|
if (cmdpreview_ns > 0 && !aborting()) {
|
||||||
if (got_quit || profile_passed_limit(timeout)) { // Too slow, disable.
|
if (got_quit || profile_passed_limit(timeout)) { // Too slow, disable.
|
||||||
set_string_option_direct("icm", -1, "", OPT_FREE, SID_NONE);
|
set_string_option_direct("icm", -1, "", OPT_FREE, SID_NONE);
|
||||||
} else if (*p_icm != NUL && pat != NULL) {
|
} else if (*p_icm != NUL && pat != NULL) {
|
||||||
|
@ -401,6 +401,40 @@ describe("'inccommand' for user commands", function()
|
|||||||
feed('e')
|
feed('e')
|
||||||
assert_alive()
|
assert_alive()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('no crash when adding highlight after :substitute #21495', function()
|
||||||
|
command('set inccommand=nosplit')
|
||||||
|
exec_lua([[
|
||||||
|
vim.api.nvim_create_user_command("Crash", function() end, {
|
||||||
|
preview = function(_, preview_ns, _)
|
||||||
|
vim.cmd("%s/text/cats/g")
|
||||||
|
vim.api.nvim_buf_add_highlight(0, preview_ns, "Search", 0, 0, -1)
|
||||||
|
return 1
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
]])
|
||||||
|
feed(':C')
|
||||||
|
screen:expect([[
|
||||||
|
{1: cats on line 1} |
|
||||||
|
more cats on line 2 |
|
||||||
|
oh no, even more cats |
|
||||||
|
will the cats ever stop |
|
||||||
|
oh well |
|
||||||
|
did the cats stop |
|
||||||
|
why won't it stop |
|
||||||
|
make the cats stop |
|
||||||
|
|
|
||||||
|
{2:~ }|
|
||||||
|
{2:~ }|
|
||||||
|
{2:~ }|
|
||||||
|
{2:~ }|
|
||||||
|
{2:~ }|
|
||||||
|
{2:~ }|
|
||||||
|
{2:~ }|
|
||||||
|
:C^ |
|
||||||
|
]])
|
||||||
|
assert_alive()
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe("'inccommand' with multiple buffers", function()
|
describe("'inccommand' with multiple buffers", function()
|
||||||
|
Reference in New Issue
Block a user