patch 9.1.0418: Cannot move to previous/next rare word

Problem:  Cannot move to previous/next rare word
          (Colin Kennedy)
Solution: Add the ]r and [r motions (Christ van Willegen)

fixes: #14773
closes: #14780

Signed-off-by: Christ van Willegen - van Noort <github.com@vanwillegen-vannoort.nl>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Christ van Willegen - van Noort
2024-05-17 18:49:27 +02:00
committed by Christian Brabandt
parent cf78d0df51
commit 8e4c4c7d87
14 changed files with 108 additions and 15 deletions

View File

@ -1,4 +1,4 @@
*spell.txt* For Vim version 9.1. Last change: 2024 May 11
*spell.txt* For Vim version 9.1. Last change: 2024 May 17
VIM REFERENCE MANUAL by Bram Moolenaar
@ -62,6 +62,17 @@ To search for the next misspelled word:
*[S*
[S Like "]S" but search backwards.
*]r*
]r Move to next "rare" word after the cursor.
A count before the command can be used to repeat.
'wrapscan' applies.
*[r*
[r Like "]r" but search backwards, find the "rare"
word before the cursor. Doesn't recognize words
split over two lines, thus may stop at words that are
not highlighted as rare.
To add words to your own word list:

View File

@ -5876,6 +5876,7 @@ ZZ editing.txt /*ZZ*
[p change.txt /*[p*
[pattern] pattern.txt /*[pattern]*
[quotex] intro.txt /*[quotex]*
[r spell.txt /*[r*
[range] cmdline.txt /*[range]*
[s spell.txt /*[s*
[star motion.txt /*[star*
@ -5904,6 +5905,7 @@ ZZ editing.txt /*ZZ*
]i tagsrch.txt /*]i*
]m motion.txt /*]m*
]p change.txt /*]p*
]r spell.txt /*]r*
]s spell.txt /*]s*
]star motion.txt /*]star*
]z fold.txt /*]z*

View File

@ -1,4 +1,4 @@
*version9.txt* For Vim version 9.1. Last change: 2024 May 05
*version9.txt* For Vim version 9.1. Last change: 2024 May 17
VIM REFERENCE MANUAL by Bram Moolenaar
@ -41587,15 +41587,17 @@ Autocommands: ~
Highlighting: ~
|hl-MsgArea| highlighting of the Command-line and messages area.
|hl-MsgArea| highlighting of the Command-line and messages area
Commands: ~
|[r| and |]r| to move the cursor to previous/next rare word
Options: ~
'winfixbuf' Keep buffer focused in a window
't_xo' Terminal uses XON/XOFF handshaking (e.g. vt420).
't_xo' Terminal uses XON/XOFF handshaking (e.g. vt420)
==============================================================================
INCOMPATIBLE CHANGES *incompatible-9.2*

View File

@ -1801,7 +1801,7 @@ win_line(
pos = wp->w_cursor;
wp->w_cursor.lnum = lnum;
wp->w_cursor.col = linecol;
len = spell_move_to(wp, FORWARD, TRUE, TRUE, &spell_hlf);
len = spell_move_to(wp, FORWARD, SMT_ALL, TRUE, &spell_hlf);
// spell_move_to() may call ml_get() and make "line" invalid
line = ml_get_buf(wp->w_buffer, lnum, FALSE);

View File

@ -10959,7 +10959,7 @@ f_spellbadword(typval_T *argvars UNUSED, typval_T *rettv)
if (argvars[0].v_type == VAR_UNKNOWN)
{
// Find the start and length of the badly spelled word.
len = spell_move_to(curwin, FORWARD, TRUE, TRUE, &attr);
len = spell_move_to(curwin, FORWARD, SMT_ALL, TRUE, &attr);
if (len != 0)
{
word = ml_get_cursor();

View File

@ -5195,7 +5195,7 @@ spell_back_to_badword(void)
{
pos_T tpos = curwin->w_cursor;
spell_bad_len = spell_move_to(curwin, BACKWARD, TRUE, TRUE, NULL);
spell_bad_len = spell_move_to(curwin, BACKWARD, SMT_ALL, TRUE, NULL);
if (curwin->w_cursor.col != tpos.col)
start_arrow(&tpos);
}

View File

@ -2593,7 +2593,7 @@ nv_zg_zw(cmdarg_T *cap, int nchar)
// off this fails and find_ident_under_cursor() is
// used below.
emsg_off++;
len = spell_move_to(curwin, FORWARD, TRUE, TRUE, NULL);
len = spell_move_to(curwin, FORWARD, SMT_ALL, TRUE, NULL);
emsg_off--;
if (len != 0 && curwin->w_cursor.col <= pos.col)
ptr = ml_get_pos(&curwin->w_cursor);
@ -4529,13 +4529,15 @@ nv_brackets(cmdarg_T *cap)
#endif
#ifdef FEAT_SPELL
// "[s", "[S", "]s" and "]S": move to next spell error.
else if (cap->nchar == 's' || cap->nchar == 'S')
// "[r", "[s", "[S", "]r", "]s" and "]S": move to next spell error.
else if (cap->nchar == 'r' || cap->nchar == 's' || cap->nchar == 'S')
{
setpcmark();
for (n = 0; n < cap->count1; ++n)
if (spell_move_to(curwin, cap->cmdchar == ']' ? FORWARD : BACKWARD,
cap->nchar == 's' ? TRUE : FALSE, FALSE, NULL) == 0)
cap->nchar == 's' ? SMT_ALL :
cap->nchar == 'r' ? SMT_RARE :
SMT_BAD, FALSE, NULL) == 0)
{
clearopbeep(cap->oap);
break;

View File

@ -6,7 +6,7 @@ int match_compoundrule(slang_T *slang, char_u *compflags);
int valid_word_prefix(int totprefcnt, int arridx, int flags, char_u *word, slang_T *slang, int cond_req);
int spell_valid_case(int wordflags, int treeflags);
int spell_check_window(win_T *wp);
int spell_move_to(win_T *wp, int dir, int allwords, int curline, hlf_T *attrp);
int spell_move_to(win_T *wp, int dir, smt_T behaviour, int curline, hlf_T *attrp);
void spell_cat_line(char_u *buf, char_u *line, int maxlen);
char_u *spell_enc(void);
slang_T *slang_alloc(char_u *lang);

View File

@ -1336,7 +1336,7 @@ no_spell_checking(win_T *wp)
spell_move_to(
win_T *wp,
int dir, // FORWARD or BACKWARD
int allwords, // TRUE for "[s"/"]s", FALSE for "[S"/"]S"
smt_T behaviour, // Behaviour of the function
int curline,
hlf_T *attrp) // return: attributes of bad word or NULL
// (only when "dir" is FORWARD)
@ -1441,7 +1441,9 @@ spell_move_to(
if (attr != HLF_COUNT)
{
// We found a bad word. Check the attribute.
if (allwords || attr == HLF_SPB)
if (behaviour == SMT_ALL
|| (behaviour == SMT_BAD && attr == HLF_SPB)
|| (behaviour == SMT_RARE && attr == HLF_SPR))
{
// When searching forward only accept a bad word after
// the cursor.

View File

@ -512,7 +512,7 @@ spell_suggest(int count)
badlen = ml_get_curline_len() - (int)curwin->w_cursor.col;
}
// Find the start of the badly spelled word.
else if (spell_move_to(curwin, FORWARD, TRUE, TRUE, NULL) == 0
else if (spell_move_to(curwin, FORWARD, SMT_ALL, TRUE, NULL) == 0
|| curwin->w_cursor.col > prev_cursor.col)
{
// No bad word or it starts after the cursor: use the word under the

View File

@ -278,6 +278,7 @@ NEW_TESTS = \
test_spell \
test_spell_utf8 \
test_spellfile \
test_spellrare \
test_startup \
test_startup_utf8 \
test_stat \
@ -521,6 +522,7 @@ NEW_TESTS_RES = \
test_spell.res \
test_spell_utf8.res \
test_spellfile.res \
test_spellrare.res \
test_startup.res \
test_stat.res \
test_statusline.res \

View File

@ -0,0 +1,61 @@
" Test spell checking
source check.vim
CheckFeature spell
" Test spellbadword() with argument, specifically to move to "rare" words
" in normal mode.
func Test_spellrareword()
set spell
" Create a small word list to test that spellbadword('...')
" can return ['...', 'rare'].
let lines =<< trim END
foo
foobar/?
foobara/?
END
call writefile(lines, 'Xwords', 'D')
mkspell! Xwords.spl Xwords
set spelllang=Xwords.spl
call assert_equal(['foobar', 'rare'], spellbadword('foo foobar'))
new
call setline(1, ['foo', '', 'foo bar foo bar foobara foo foo foo foobar', '', 'End'])
set spell wrapscan
normal ]s
call assert_equal('foo', expand('<cword>'))
normal ]s
call assert_equal('bar', expand('<cword>'))
normal ]r
call assert_equal('foobara', expand('<cword>'))
normal ]r
call assert_equal('foobar', expand('<cword>'))
normal ]r
call assert_equal('foobara', expand('<cword>'))
normal 2]r
call assert_equal('foobara', expand('<cword>'))
normal [r
call assert_equal('foobar', expand('<cword>'))
normal [r
call assert_equal('foobara', expand('<cword>'))
normal [r
call assert_equal('foobar', expand('<cword>'))
normal 2[r
call assert_equal('foobar', expand('<cword>'))
bwipe!
set nospell
call delete('Xwords.spl')
set spelllang&
set spell&
" set 'encoding' to clear the word list
set encoding=utf-8
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
418,
/**/
417,
/**/

View File

@ -1529,6 +1529,15 @@ typedef enum
'*', '#', '_', '!', '.', 'o', 'q', \
'z', 'Z', 'g'}
/*
* Values for behaviour in spell_move_to
*/
typedef enum
{
SMT_ALL = 0 // Move to "all" words
, SMT_BAD // Move to "bad" words only
, SMT_RARE // Move to "rare" words only
} smt_T;
/*
* Boolean constants
*/