]> granicus.if.org Git - vim/commitdiff
patch 8.2.3110: a pattern that matches the cursor position is complicated v8.2.3110
authorBram Moolenaar <Bram@vim.org>
Mon, 5 Jul 2021 18:15:23 +0000 (20:15 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 5 Jul 2021 18:15:23 +0000 (20:15 +0200)
Problem:    A pattern that matches the cursor position is bit complicated.
Solution:   Use a dot to indicate the cursor line and column. (Christian
            Brabandt, closes #8497, closes #8179)

runtime/doc/pattern.txt
src/errors.h
src/regexp_bt.c
src/regexp_nfa.c
src/testdir/test_regexp_latin.vim
src/version.c

index c23fdb444affd1b1cd7d86f05c2a0aab9a612dcd..962882765e9f745f330b48cbd6a0cca0bb8f92ba 100644 (file)
@@ -929,13 +929,20 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on):
 \%23l  Matches in a specific line.
 \%<23l Matches above a specific line (lower line number).
 \%>23l Matches below a specific line (higher line number).
+\%.l    Matches at the cursor line.
+\%<.l   Matches above the cursor line.
+\%>.l   Matches below the cursor line.
        These three can be used to match specific lines in a buffer.  The "23"
        can be any line number.  The first line is 1.
        WARNING: When inserting or deleting lines Vim does not automatically
        update the matches.  This means Syntax highlighting quickly becomes
-       wrong.
+       wrong.  Also when refering to the cursor position (".") and
+       the cursor moves the display isn't updated for this change.  An update
+       is done when using the |CTRL-L| command (the whole screen is updated).
        Example, to highlight the line where the cursor currently is: >
-               :exe '/\%' . line(".") . 'l.*'
+               :exe '/\%' . line(".") . 'l'
+<      Alternatively use: >
+               /\%.l
 <      When 'hlsearch' is set and you move the cursor around and make changes
        this will clearly show when the match is updated or not.
 
@@ -943,15 +950,23 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on):
 \%23c  Matches in a specific column.
 \%<23c Matches before a specific column.
 \%>23c Matches after a specific column.
+\%.c    Matches at the cursor column.
+\%<.c   Matches before the cursor column.
+\%>.c   Matches after the cursor column.
        These three can be used to match specific columns in a buffer or
        string.  The "23" can be any column number.  The first column is 1.
        Actually, the column is the byte number (thus it's not exactly right
        for multibyte characters).
        WARNING: When inserting or deleting text Vim does not automatically
        update the matches.  This means Syntax highlighting quickly becomes
-       wrong.
+       wrong.  Also when refering to the cursor position (".") and
+       the cursor moves the display isn't updated for this change.  An update
+       is done when using the |CTRL-L| command (the whole screen is updated).
+
        Example, to highlight the column where the cursor currently is: >
                :exe '/\%' . col(".") . 'c'
+<      Alternatively use: >
+               /\%.c
 <      When 'hlsearch' is set and you move the cursor around and make changes
        this will clearly show when the match is updated or not.
        Example for matching a single byte in column 44: >
@@ -962,6 +977,9 @@ $   At end of pattern or in front of "\|", "\)" or "\n" ('magic' on):
 \%23v  Matches in a specific virtual column.
 \%<23v Matches before a specific virtual column.
 \%>23v Matches after a specific virtual column.
+\%.v    Matches at the current virtual column.
+\%<.v   Matches before the current virtual column.
+\%>.v   Matches after the current virtual column.
        These three can be used to match specific virtual columns in a buffer
        or string.  When not matching with a buffer in a window, the option
        values of the current window are used (e.g., 'tabstop').
@@ -971,13 +989,18 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on):
        one screen character.
        WARNING: When inserting or deleting text Vim does not automatically
        update highlighted matches.  This means Syntax highlighting quickly
-       becomes wrong.
+       becomes wrong.  Also when refering to the cursor position (".") and
+       the cursor moves the display isn't updated for this change.  An update
+       is done when using the |CTRL-L| command (the whole screen is updated).
        Example, to highlight all the characters after virtual column 72: >
                /\%>72v.*
 <      When 'hlsearch' is set and you move the cursor around and make changes
        this will clearly show when the match is updated or not.
        To match the text up to column 17: >
                /^.*\%17v
+<      To match all characters after the current virtual column (where the
+       cursor is): >
+               /\%>.v.*
 <      Column 17 is not included, because this is a |/zero-width| match. To
        include the column use: >
                /^.*\%17v.
index f2624dfc1d99b4f33efb8dba9be95c00d2688733..7524b804689202abb73d889531bcf217b27ed448 100644 (file)
@@ -488,3 +488,5 @@ EXTERN char e_no_white_space_allowed_after_str_str[]
        INIT(= N_("E1202: No white space allowed after '%s': %s"));
 EXTERN char e_dot_can_only_be_used_on_dictionary_str[]
        INIT(= N_("E1203: Dot can only be used on a dictionary: %s"));
+EXTERN char e_regexp_number_after_dot_pos_search[]
+       INIT(= N_("E1204: No Number allowed after .: '\\%%%c'"));
index 70ddfe986f0fc60f62c392ed8ce8eb9e40c7ca34..dae6d519be58283de07e430e06bb2f2d70b260f0 100644 (file)
@@ -1628,14 +1628,20 @@ regatom(int *flagp)
 
                default:
                          if (VIM_ISDIGIT(c) || c == '<' || c == '>'
-                                                                || c == '\'')
+                                               || c == '\'' || c == '.')
                          {
                              long_u    n = 0;
                              int       cmp;
+                             int       cur = FALSE;
 
                              cmp = c;
                              if (cmp == '<' || cmp == '>')
                                  c = getchr();
+                             if (no_Magic(c) == '.')
+                             {
+                                 cur = TRUE;
+                                 c = getchr();
+                             }
                              while (VIM_ISDIGIT(c))
                              {
                                  n = n * 10 + (c - '0');
@@ -1657,16 +1663,42 @@ regatom(int *flagp)
                              }
                              else if (c == 'l' || c == 'c' || c == 'v')
                              {
+                                 if (cur && n)
+                                 {
+                                   semsg(_(e_regexp_number_after_dot_pos_search), no_Magic(c));
+                                   rc_did_emsg = TRUE;
+                                   return NULL;
+                                 }
                                  if (c == 'l')
                                  {
+                                     if (cur)
+                                         n = curwin->w_cursor.lnum;
                                      ret = regnode(RE_LNUM);
                                      if (save_prev_at_start)
                                          at_start = TRUE;
                                  }
                                  else if (c == 'c')
+                                 {
+                                     if (cur)
+                                     {
+                                         n = curwin->w_cursor.col;
+                                         n++;
+                                     }
                                      ret = regnode(RE_COL);
+                                 }
                                  else
+                                 {
+                                     if (cur)
+                                     {
+                                         colnr_T vcol = 0;
+
+                                         getvvcol(curwin, &curwin->w_cursor,
+                                                           NULL, NULL, &vcol);
+                                         ++vcol;
+                                         n = vcol;
+                                     }
                                      ret = regnode(RE_VCOL);
+                                 }
                                  if (ret == JUST_CALC_SIZE)
                                      regsize += 5;
                                  else
index 2ed18685d9ddd311aac0b6ce4644ce2e16a15c84..7dff195ea24423bf1837aa49ee98cb2d375bec2e 100644 (file)
@@ -1707,12 +1707,23 @@ nfa_regatom(void)
                    {
                        long_u  n = 0;
                        int     cmp = c;
+                       int     cur = FALSE;
 
                        if (c == '<' || c == '>')
                            c = getchr();
+                       if (no_Magic(c) == '.')
+                       {
+                           cur = TRUE;
+                           c = getchr();
+                       }
                        while (VIM_ISDIGIT(c))
                        {
-                           long_u tmp = n * 10 + (c - '0');
+                           long_u tmp;
+
+                           if (cur)
+                               semsg(_(e_regexp_number_after_dot_pos_search),
+                                                                no_Magic(c));
+                           tmp = n * 10 + (c - '0');
 
                            if (tmp < n)
                            {
@@ -1729,6 +1740,8 @@ nfa_regatom(void)
 
                            if (c == 'l')
                            {
+                               if (cur)
+                                   n = curwin->w_cursor.lnum;
                                // \%{n}l  \%{n}<l  \%{n}>l
                                EMIT(cmp == '<' ? NFA_LNUM_LT :
                                     cmp == '>' ? NFA_LNUM_GT : NFA_LNUM);
@@ -1736,11 +1749,26 @@ nfa_regatom(void)
                                    at_start = TRUE;
                            }
                            else if (c == 'c')
+                           {
+                               if (cur)
+                               {
+                                   n = curwin->w_cursor.col;
+                                   n++;
+                               }
                                // \%{n}c  \%{n}<c  \%{n}>c
                                EMIT(cmp == '<' ? NFA_COL_LT :
                                     cmp == '>' ? NFA_COL_GT : NFA_COL);
+                           }
                            else
                            {
+                               if (cur)
+                               {
+                                   colnr_T vcol = 0;
+
+                                   getvvcol(curwin, &curwin->w_cursor,
+                                                           NULL, NULL, &vcol);
+                                   n = ++vcol;
+                               }
                                // \%{n}v  \%{n}<v  \%{n}>v
                                EMIT(cmp == '<' ? NFA_VCOL_LT :
                                     cmp == '>' ? NFA_VCOL_GT : NFA_VCOL);
index e53a8da5882de881e577b05994a3e0880a6f5dd4..c487b274d2e0480bc975a5fd254b106b0b8aaab3 100644 (file)
@@ -947,4 +947,94 @@ func Test_regexp_last_subst_string()
   close!
 endfunc
 
+" Check patterns matching cursor position.
+func s:curpos_test2()
+  new
+  call setline(1, ['1', '2 foobar eins zwei drei vier fünf sechse',
+        \ '3 foobar eins zwei drei vier fünf sechse',
+        \ '4 foobar eins zwei drei vier fünf sechse',
+        \ '5   foobar eins zwei drei vier fünf sechse',
+        \ '6   foobar eins zwei drei vier fünf sechse',
+        \ '7   foobar eins zwei drei vier fünf sechse'])
+  call setpos('.', [0, 2, 10, 0])
+  s/\%.c.*//g
+  call setpos('.', [0, 3, 15, 0])
+  s/\%.l.*//g
+  call setpos('.', [0, 5, 3, 0])
+  s/\%.v.*/_/g
+  call assert_equal(['1',
+        \ '2 foobar ',
+        \ '',
+        \ '4 foobar eins zwei drei vier fünf sechse',
+        \ '5   _',
+        \ '6   foobar eins zwei drei vier fünf sechse',
+        \ '7   foobar eins zwei drei vier fünf sechse'],
+        \ getline(1, '$'))
+  call assert_fails('call search("\\%.1l")', 'E1204:')
+  call assert_fails('call search("\\%.1c")', 'E1204:')
+  call assert_fails('call search("\\%.1v")', 'E1204:')
+  bwipe!
+endfunc
+
+" Check patterns matching before or after cursor position.
+func s:curpos_test3()
+  new
+  call setline(1, ['1', '2 foobar eins zwei drei vier fünf sechse',
+        \ '3 foobar eins zwei drei vier fünf sechse',
+        \ '4 foobar eins zwei drei vier fünf sechse',
+        \ '5   foobar eins zwei drei vier fünf sechse',
+        \ '6   foobar eins zwei drei vier fünf sechse',
+        \ '7   foobar eins zwei drei vier fünf sechse'])
+  call setpos('.', [0, 2, 10, 0])
+  " Note: This removes all columns, except for the column directly in front of
+  " the cursor. Bug????
+  :s/^.*\%<.c//
+  call setpos('.', [0, 3, 10, 0])
+  :s/\%>.c.*$//
+  call setpos('.', [0, 5, 4, 0])
+  " Note: This removes all columns, except for the column directly in front of
+  " the cursor. Bug????
+  :s/^.*\%<.v/_/
+  call setpos('.', [0, 6, 4, 0])
+  :s/\%>.v.*$/_/
+  call assert_equal(['1',
+        \ ' eins zwei drei vier fünf sechse',
+        \ '3 foobar e',
+        \ '4 foobar eins zwei drei vier fünf sechse',
+        \ '_foobar eins zwei drei vier fünf sechse',
+        \ '6   fo_',
+        \ '7   foobar eins zwei drei vier fünf sechse'],
+        \ getline(1, '$'))
+  sil %d
+  call setline(1, ['1', '2 foobar eins zwei drei vier fünf sechse',
+        \ '3 foobar eins zwei drei vier fünf sechse',
+        \ '4 foobar eins zwei drei vier fünf sechse',
+        \ '5   foobar eins zwei drei vier fünf sechse',
+        \ '6   foobar eins zwei drei vier fünf sechse',
+        \ '7   foobar eins zwei drei vier fünf sechse'])
+  call setpos('.', [0, 4, 4, 0])
+  %s/\%<.l.*//
+  call setpos('.', [0, 5, 4, 0])
+  %s/\%>.l.*//
+  call assert_equal(['', '', '',
+        \ '4 foobar eins zwei drei vier fünf sechse',
+        \ '5   foobar eins zwei drei vier fünf sechse',
+        \ '', ''],
+        \ getline(1, '$'))
+  bwipe!
+endfunc
+
+" Test that matching below, at or after the
+" cursor position work
+func Test_matching_pos()
+  for val in range(3)
+    exe "set re=" .. val
+    " Match at cursor position
+    call s:curpos_test2()
+    " Match before or after cursor position
+    call s:curpos_test3()
+  endfor
+  set re&
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index a36ec80cf464808f455ce882f1adc5d4a1e3fefc..b448822d5ae90f8d192f023bf2c133be040826fd 100644 (file)
@@ -755,6 +755,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3110,
 /**/
     3109,
 /**/