commit 563f9ef7994a35686419b4524cd772c97960dac1
parent 62135f5a578a8e9894c511ebf37855ce7b2e1917
Author: luukvbaal <luukvbaal@gmail.com>
Date: Sun, 1 Mar 2026 09:21:48 +0100
vim-patch:9.2.0081: Failed "z=" does not reset 'nospell' setting (#38109)
Problem: When z= fails due to no word being found, 'spelllang' being
unset or a multiline visual selection, 'nospell' is not
restored.
Solution: Jump to where the user configured value of 'spell' is restored
instead of returning early (Luuk van Baal).
closes: vim/vim#19525
https://github.com/vim/vim/commit/eba078fc47b6e0a5b6bc032ab31f4296ed2ff2a6
Diffstat:
3 files changed, 30 insertions(+), 15 deletions(-)
diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c
@@ -439,11 +439,7 @@ int spell_check_sps(void)
void spell_suggest(int count)
{
pos_T prev_cursor = curwin->w_cursor;
- char wcopy[MAXWLEN + 2];
- suginfo_T sug;
- suggest_T *stp;
bool mouse_used = false;
- int selected = count;
int badlen = 0;
int msg_scroll_save = msg_scroll;
const int wo_spell_save = curwin->w_p_spell;
@@ -455,7 +451,7 @@ void spell_suggest(int count)
if (*curwin->w_s->b_p_spl == NUL) {
emsg(_(e_no_spell));
- return;
+ goto skip;
}
if (VIsual_active) {
@@ -463,7 +459,7 @@ void spell_suggest(int count)
// a multi-line selection.
if (curwin->w_cursor.lnum != VIsual.lnum) {
vim_beep(kOptBoFlagSpell);
- return;
+ goto skip;
}
badlen = (int)curwin->w_cursor.col - (int)VIsual.col;
if (badlen < 0) {
@@ -481,11 +477,11 @@ void spell_suggest(int count)
// No bad word or it starts after the cursor: use the word under the
// cursor.
curwin->w_cursor = prev_cursor;
- char *line = get_cursor_line_ptr();
- char *p = line + curwin->w_cursor.col;
+ char *curline = get_cursor_line_ptr();
+ char *p = curline + curwin->w_cursor.col;
// Backup to before start of word.
- while (p > line && spell_iswordp_nmw(p, curwin)) {
- MB_PTR_BACK(line, p);
+ while (p > curline && spell_iswordp_nmw(p, curwin)) {
+ MB_PTR_BACK(curline, p);
}
// Forward to start of word.
while (*p != NUL && !spell_iswordp_nmw(p, curwin)) {
@@ -494,9 +490,9 @@ void spell_suggest(int count)
if (!spell_iswordp_nmw(p, curwin)) { // No word found.
beep_flush();
- return;
+ goto skip;
}
- curwin->w_cursor.col = (colnr_T)(p - line);
+ curwin->w_cursor.col = (colnr_T)(p - curline);
}
// Get the word and its length.
@@ -510,10 +506,12 @@ void spell_suggest(int count)
// Get the list of suggestions. Limit to 'lines' - 2 or the number in
// 'spellsuggest', whatever is smaller.
+ suginfo_T sug;
int limit = MIN(sps_limit, Rows - 2);
spell_find_suggest(line + curwin->w_cursor.col, badlen, &sug, limit,
true, need_cap, true);
+ int selected = count;
msg_ext_set_kind("confirm");
if (GA_EMPTY(&sug.su_ga)) {
msg(_("Sorry, no suggestions"), 0);
@@ -543,10 +541,11 @@ void spell_suggest(int count)
msg_scroll = true;
for (int i = 0; i < sug.su_ga.ga_len; i++) {
- stp = &SUG(sug.su_ga, i);
+ suggest_T *stp = &SUG(sug.su_ga, i);
// The suggested word may replace only part of the bad word, add
// the not replaced part. But only when it's not getting too long.
+ char wcopy[MAXWLEN + 2];
xstrlcpy(wcopy, stp->st_word, MAXWLEN + 1);
int el = sug.su_badlen - stp->st_orglen;
if (el > 0 && stp->st_wordlen + el <= MAXWLEN) {
@@ -609,7 +608,7 @@ void spell_suggest(int count)
XFREE_CLEAR(repl_from);
XFREE_CLEAR(repl_to);
- stp = &SUG(sug.su_ga, selected - 1);
+ suggest_T *stp = &SUG(sug.su_ga, selected - 1);
if (sug.su_badlen > stp->st_orglen) {
// Replacing less than "su_badlen", append the remainder to
// repl_to.
@@ -649,6 +648,7 @@ void spell_suggest(int count)
spell_find_cleanup(&sug);
xfree(line);
+skip:
curwin->w_p_spell = wo_spell_save;
}
diff --git a/test/old/testdir/test_spell.vim b/test/old/testdir/test_spell.vim
@@ -1579,4 +1579,18 @@ let g:test_data_aff_sal = [
\"SAL Z S",
\ ]
+func Test_suggest_spell_restore()
+ norm! z=
+ call assert_equal(0, &spell)
+ set spelllang=
+ sil! norm! z=
+ call assert_equal(0, &spell)
+ set spelllang=en
+ call setline(1, ['1','2'])
+ norm! vjz=
+ call assert_equal(0, &spell)
+ set spelllang&
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_spell_utf8.vim b/test/old/testdir/test_spell_utf8.vim
@@ -809,13 +809,14 @@ endfunc
func Test_check_empty_line()
" This was using freed memory
+ set spell
enew
spellgood! fl
norm z=
norm yy
sil! norm P]svc
norm P]s
-
+ set spell&
bwipe!
endfunc