patch 9.1.0418: Cannot move to previous/next rare word

Commit: 
https://github.com/vim/vim/commit/8e4c4c7d87def2b100a5d64dc518ef85d9de8765
Author: Christ van Willegen - van Noort <github....@vanwillegen-vannoort.nl>
Date:   Fri May 17 18:49:27 2024 +0200

    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....@vanwillegen-vannoort.nl>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/doc/spell.txt b/runtime/doc/spell.txt
index ab3b12045..809e3a8d3 100644
--- a/runtime/doc/spell.txt
+++ b/runtime/doc/spell.txt
@@ -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:
 
diff --git a/runtime/doc/tags b/runtime/doc/tags
index d354df1ee..2c3fd7f9d 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -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*
diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt
index 192c3ee75..1c5a29f20 100644
--- a/runtime/doc/version9.txt
+++ b/runtime/doc/version9.txt
@@ -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*
diff --git a/src/drawline.c b/src/drawline.c
index 81577be42..9502fc53a 100644
--- a/src/drawline.c
+++ b/src/drawline.c
@@ -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);
diff --git a/src/evalfunc.c b/src/evalfunc.c
index fecdc4351..cd3a6fd80 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -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();
diff --git a/src/insexpand.c b/src/insexpand.c
index 93a56a8bd..1520d5760 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -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);
 }
diff --git a/src/normal.c b/src/normal.c
index fef282647..580eb7229 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -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;
diff --git a/src/proto/spell.pro b/src/proto/spell.pro
index 98a135349..680bf34f4 100644
--- a/src/proto/spell.pro
+++ b/src/proto/spell.pro
@@ -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);
diff --git a/src/spell.c b/src/spell.c
index 43c521dde..3ae484c14 100644
--- a/src/spell.c
+++ b/src/spell.c
@@ -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.
diff --git a/src/spellsuggest.c b/src/spellsuggest.c
index c6e61832d..b305bfb83 100644
--- a/src/spellsuggest.c
+++ b/src/spellsuggest.c
@@ -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
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index b41f5f49f..a80b1300e 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -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 \
diff --git a/src/testdir/test_spellrare.vim b/src/testdir/test_spellrare.vim
new file mode 100644
index 000000000..bbb13c27c
--- /dev/null
+++ b/src/testdir/test_spellrare.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index 682a46873..ad3b585cd 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    418,
 /**/
     417,
 /**/
diff --git a/src/vim.h b/src/vim.h
index f359245fa..654e52344 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -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
  */

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1s80w8-007o4H-8G%40256bit.org.

Raspunde prin e-mail lui