forked from aniani/vim
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:
committed by
Christian Brabandt
parent
cf78d0df51
commit
8e4c4c7d87
@@ -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
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@@ -62,6 +62,17 @@ To search for the next misspelled word:
|
|||||||
*[S*
|
*[S*
|
||||||
[S Like "]S" but search backwards.
|
[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:
|
To add words to your own word list:
|
||||||
|
|
||||||
|
@@ -5876,6 +5876,7 @@ ZZ editing.txt /*ZZ*
|
|||||||
[p change.txt /*[p*
|
[p change.txt /*[p*
|
||||||
[pattern] pattern.txt /*[pattern]*
|
[pattern] pattern.txt /*[pattern]*
|
||||||
[quotex] intro.txt /*[quotex]*
|
[quotex] intro.txt /*[quotex]*
|
||||||
|
[r spell.txt /*[r*
|
||||||
[range] cmdline.txt /*[range]*
|
[range] cmdline.txt /*[range]*
|
||||||
[s spell.txt /*[s*
|
[s spell.txt /*[s*
|
||||||
[star motion.txt /*[star*
|
[star motion.txt /*[star*
|
||||||
@@ -5904,6 +5905,7 @@ ZZ editing.txt /*ZZ*
|
|||||||
]i tagsrch.txt /*]i*
|
]i tagsrch.txt /*]i*
|
||||||
]m motion.txt /*]m*
|
]m motion.txt /*]m*
|
||||||
]p change.txt /*]p*
|
]p change.txt /*]p*
|
||||||
|
]r spell.txt /*]r*
|
||||||
]s spell.txt /*]s*
|
]s spell.txt /*]s*
|
||||||
]star motion.txt /*]star*
|
]star motion.txt /*]star*
|
||||||
]z fold.txt /*]z*
|
]z fold.txt /*]z*
|
||||||
|
@@ -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
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@@ -41587,15 +41587,17 @@ Autocommands: ~
|
|||||||
|
|
||||||
Highlighting: ~
|
Highlighting: ~
|
||||||
|
|
||||||
|hl-MsgArea| highlighting of the Command-line and messages area.
|
|hl-MsgArea| highlighting of the Command-line and messages area
|
||||||
|
|
||||||
Commands: ~
|
Commands: ~
|
||||||
|
|
||||||
|
|[r| and |]r| to move the cursor to previous/next rare word
|
||||||
|
|
||||||
|
|
||||||
Options: ~
|
Options: ~
|
||||||
|
|
||||||
'winfixbuf' Keep buffer focused in a window
|
'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*
|
INCOMPATIBLE CHANGES *incompatible-9.2*
|
||||||
|
@@ -1801,7 +1801,7 @@ win_line(
|
|||||||
pos = wp->w_cursor;
|
pos = wp->w_cursor;
|
||||||
wp->w_cursor.lnum = lnum;
|
wp->w_cursor.lnum = lnum;
|
||||||
wp->w_cursor.col = linecol;
|
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
|
// spell_move_to() may call ml_get() and make "line" invalid
|
||||||
line = ml_get_buf(wp->w_buffer, lnum, FALSE);
|
line = ml_get_buf(wp->w_buffer, lnum, FALSE);
|
||||||
|
@@ -10959,7 +10959,7 @@ f_spellbadword(typval_T *argvars UNUSED, typval_T *rettv)
|
|||||||
if (argvars[0].v_type == VAR_UNKNOWN)
|
if (argvars[0].v_type == VAR_UNKNOWN)
|
||||||
{
|
{
|
||||||
// Find the start and length of the badly spelled word.
|
// 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)
|
if (len != 0)
|
||||||
{
|
{
|
||||||
word = ml_get_cursor();
|
word = ml_get_cursor();
|
||||||
|
@@ -5195,7 +5195,7 @@ spell_back_to_badword(void)
|
|||||||
{
|
{
|
||||||
pos_T tpos = curwin->w_cursor;
|
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)
|
if (curwin->w_cursor.col != tpos.col)
|
||||||
start_arrow(&tpos);
|
start_arrow(&tpos);
|
||||||
}
|
}
|
||||||
|
10
src/normal.c
10
src/normal.c
@@ -2593,7 +2593,7 @@ nv_zg_zw(cmdarg_T *cap, int nchar)
|
|||||||
// off this fails and find_ident_under_cursor() is
|
// off this fails and find_ident_under_cursor() is
|
||||||
// used below.
|
// used below.
|
||||||
emsg_off++;
|
emsg_off++;
|
||||||
len = spell_move_to(curwin, FORWARD, TRUE, TRUE, NULL);
|
len = spell_move_to(curwin, FORWARD, SMT_ALL, TRUE, NULL);
|
||||||
emsg_off--;
|
emsg_off--;
|
||||||
if (len != 0 && curwin->w_cursor.col <= pos.col)
|
if (len != 0 && curwin->w_cursor.col <= pos.col)
|
||||||
ptr = ml_get_pos(&curwin->w_cursor);
|
ptr = ml_get_pos(&curwin->w_cursor);
|
||||||
@@ -4529,13 +4529,15 @@ nv_brackets(cmdarg_T *cap)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FEAT_SPELL
|
#ifdef FEAT_SPELL
|
||||||
// "[s", "[S", "]s" and "]S": move to next spell error.
|
// "[r", "[s", "[S", "]r", "]s" and "]S": move to next spell error.
|
||||||
else if (cap->nchar == 's' || cap->nchar == 'S')
|
else if (cap->nchar == 'r' || cap->nchar == 's' || cap->nchar == 'S')
|
||||||
{
|
{
|
||||||
setpcmark();
|
setpcmark();
|
||||||
for (n = 0; n < cap->count1; ++n)
|
for (n = 0; n < cap->count1; ++n)
|
||||||
if (spell_move_to(curwin, cap->cmdchar == ']' ? FORWARD : BACKWARD,
|
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);
|
clearopbeep(cap->oap);
|
||||||
break;
|
break;
|
||||||
|
@@ -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 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_valid_case(int wordflags, int treeflags);
|
||||||
int spell_check_window(win_T *wp);
|
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);
|
void spell_cat_line(char_u *buf, char_u *line, int maxlen);
|
||||||
char_u *spell_enc(void);
|
char_u *spell_enc(void);
|
||||||
slang_T *slang_alloc(char_u *lang);
|
slang_T *slang_alloc(char_u *lang);
|
||||||
|
@@ -1336,7 +1336,7 @@ no_spell_checking(win_T *wp)
|
|||||||
spell_move_to(
|
spell_move_to(
|
||||||
win_T *wp,
|
win_T *wp,
|
||||||
int dir, // FORWARD or BACKWARD
|
int dir, // FORWARD or BACKWARD
|
||||||
int allwords, // TRUE for "[s"/"]s", FALSE for "[S"/"]S"
|
smt_T behaviour, // Behaviour of the function
|
||||||
int curline,
|
int curline,
|
||||||
hlf_T *attrp) // return: attributes of bad word or NULL
|
hlf_T *attrp) // return: attributes of bad word or NULL
|
||||||
// (only when "dir" is FORWARD)
|
// (only when "dir" is FORWARD)
|
||||||
@@ -1441,7 +1441,9 @@ spell_move_to(
|
|||||||
if (attr != HLF_COUNT)
|
if (attr != HLF_COUNT)
|
||||||
{
|
{
|
||||||
// We found a bad word. Check the attribute.
|
// 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
|
// When searching forward only accept a bad word after
|
||||||
// the cursor.
|
// the cursor.
|
||||||
|
@@ -512,7 +512,7 @@ spell_suggest(int count)
|
|||||||
badlen = ml_get_curline_len() - (int)curwin->w_cursor.col;
|
badlen = ml_get_curline_len() - (int)curwin->w_cursor.col;
|
||||||
}
|
}
|
||||||
// Find the start of the badly spelled word.
|
// 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)
|
|| curwin->w_cursor.col > prev_cursor.col)
|
||||||
{
|
{
|
||||||
// No bad word or it starts after the cursor: use the word under the
|
// No bad word or it starts after the cursor: use the word under the
|
||||||
|
@@ -278,6 +278,7 @@ NEW_TESTS = \
|
|||||||
test_spell \
|
test_spell \
|
||||||
test_spell_utf8 \
|
test_spell_utf8 \
|
||||||
test_spellfile \
|
test_spellfile \
|
||||||
|
test_spellrare \
|
||||||
test_startup \
|
test_startup \
|
||||||
test_startup_utf8 \
|
test_startup_utf8 \
|
||||||
test_stat \
|
test_stat \
|
||||||
@@ -521,6 +522,7 @@ NEW_TESTS_RES = \
|
|||||||
test_spell.res \
|
test_spell.res \
|
||||||
test_spell_utf8.res \
|
test_spell_utf8.res \
|
||||||
test_spellfile.res \
|
test_spellfile.res \
|
||||||
|
test_spellrare.res \
|
||||||
test_startup.res \
|
test_startup.res \
|
||||||
test_stat.res \
|
test_stat.res \
|
||||||
test_statusline.res \
|
test_statusline.res \
|
||||||
|
61
src/testdir/test_spellrare.vim
Normal file
61
src/testdir/test_spellrare.vim
Normal 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
|
@@ -704,6 +704,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
418,
|
||||||
/**/
|
/**/
|
||||||
417,
|
417,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -1529,6 +1529,15 @@ typedef enum
|
|||||||
'*', '#', '_', '!', '.', 'o', 'q', \
|
'*', '#', '_', '!', '.', 'o', 'q', \
|
||||||
'z', 'Z', 'g'}
|
'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
|
* Boolean constants
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user