Skip to content

Commit 04db26b

Browse files
committed
patch 8.2.3110: a pattern that matches the cursor position is complicated
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)
1 parent f6d8779 commit 04db26b

File tree

6 files changed

+183
-6
lines changed

6 files changed

+183
-6
lines changed

runtime/doc/pattern.txt

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -929,29 +929,44 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on):
929929
\%23l Matches in a specific line.
930930
\%<23l Matches above a specific line (lower line number).
931931
\%>23l Matches below a specific line (higher line number).
932+
\%.l Matches at the cursor line.
933+
\%<.l Matches above the cursor line.
934+
\%>.l Matches below the cursor line.
932935
These three can be used to match specific lines in a buffer. The "23"
933936
can be any line number. The first line is 1.
934937
WARNING: When inserting or deleting lines Vim does not automatically
935938
update the matches. This means Syntax highlighting quickly becomes
936-
wrong.
939+
wrong. Also when refering to the cursor position (".") and
940+
the cursor moves the display isn't updated for this change. An update
941+
is done when using the |CTRL-L| command (the whole screen is updated).
937942
Example, to highlight the line where the cursor currently is: >
938-
:exe '/\%' . line(".") . 'l.*'
943+
:exe '/\%' . line(".") . 'l'
944+
< Alternatively use: >
945+
/\%.l
939946
< When 'hlsearch' is set and you move the cursor around and make changes
940947
this will clearly show when the match is updated or not.
941948

942949
*/\%c* */\%>c* */\%<c*
943950
\%23c Matches in a specific column.
944951
\%<23c Matches before a specific column.
945952
\%>23c Matches after a specific column.
953+
\%.c Matches at the cursor column.
954+
\%<.c Matches before the cursor column.
955+
\%>.c Matches after the cursor column.
946956
These three can be used to match specific columns in a buffer or
947957
string. The "23" can be any column number. The first column is 1.
948958
Actually, the column is the byte number (thus it's not exactly right
949959
for multibyte characters).
950960
WARNING: When inserting or deleting text Vim does not automatically
951961
update the matches. This means Syntax highlighting quickly becomes
952-
wrong.
962+
wrong. Also when refering to the cursor position (".") and
963+
the cursor moves the display isn't updated for this change. An update
964+
is done when using the |CTRL-L| command (the whole screen is updated).
965+
953966
Example, to highlight the column where the cursor currently is: >
954967
:exe '/\%' . col(".") . 'c'
968+
< Alternatively use: >
969+
/\%.c
955970
< When 'hlsearch' is set and you move the cursor around and make changes
956971
this will clearly show when the match is updated or not.
957972
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):
962977
\%23v Matches in a specific virtual column.
963978
\%<23v Matches before a specific virtual column.
964979
\%>23v Matches after a specific virtual column.
980+
\%.v Matches at the current virtual column.
981+
\%<.v Matches before the current virtual column.
982+
\%>.v Matches after the current virtual column.
965983
These three can be used to match specific virtual columns in a buffer
966984
or string. When not matching with a buffer in a window, the option
967985
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):
971989
one screen character.
972990
WARNING: When inserting or deleting text Vim does not automatically
973991
update highlighted matches. This means Syntax highlighting quickly
974-
becomes wrong.
992+
becomes wrong. Also when refering to the cursor position (".") and
993+
the cursor moves the display isn't updated for this change. An update
994+
is done when using the |CTRL-L| command (the whole screen is updated).
975995
Example, to highlight all the characters after virtual column 72: >
976996
/\%>72v.*
977997
< When 'hlsearch' is set and you move the cursor around and make changes
978998
this will clearly show when the match is updated or not.
979999
To match the text up to column 17: >
9801000
/^.*\%17v
1001+
< To match all characters after the current virtual column (where the
1002+
cursor is): >
1003+
/\%>.v.*
9811004
< Column 17 is not included, because this is a |/zero-width| match. To
9821005
include the column use: >
9831006
/^.*\%17v.

src/errors.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,3 +488,5 @@ EXTERN char e_no_white_space_allowed_after_str_str[]
488488
INIT(= N_("E1202: No white space allowed after '%s': %s"));
489489
EXTERN char e_dot_can_only_be_used_on_dictionary_str[]
490490
INIT(= N_("E1203: Dot can only be used on a dictionary: %s"));
491+
EXTERN char e_regexp_number_after_dot_pos_search[]
492+
INIT(= N_("E1204: No Number allowed after .: '\\%%%c'"));

src/regexp_bt.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1628,14 +1628,20 @@ regatom(int *flagp)
16281628

16291629
default:
16301630
if (VIM_ISDIGIT(c) || c == '<' || c == '>'
1631-
|| c == '\'')
1631+
|| c == '\'' || c == '.')
16321632
{
16331633
long_u n = 0;
16341634
int cmp;
1635+
int cur = FALSE;
16351636

16361637
cmp = c;
16371638
if (cmp == '<' || cmp == '>')
16381639
c = getchr();
1640+
if (no_Magic(c) == '.')
1641+
{
1642+
cur = TRUE;
1643+
c = getchr();
1644+
}
16391645
while (VIM_ISDIGIT(c))
16401646
{
16411647
n = n * 10 + (c - '0');
@@ -1657,16 +1663,42 @@ regatom(int *flagp)
16571663
}
16581664
else if (c == 'l' || c == 'c' || c == 'v')
16591665
{
1666+
if (cur && n)
1667+
{
1668+
semsg(_(e_regexp_number_after_dot_pos_search), no_Magic(c));
1669+
rc_did_emsg = TRUE;
1670+
return NULL;
1671+
}
16601672
if (c == 'l')
16611673
{
1674+
if (cur)
1675+
n = curwin->w_cursor.lnum;
16621676
ret = regnode(RE_LNUM);
16631677
if (save_prev_at_start)
16641678
at_start = TRUE;
16651679
}
16661680
else if (c == 'c')
1681+
{
1682+
if (cur)
1683+
{
1684+
n = curwin->w_cursor.col;
1685+
n++;
1686+
}
16671687
ret = regnode(RE_COL);
1688+
}
16681689
else
1690+
{
1691+
if (cur)
1692+
{
1693+
colnr_T vcol = 0;
1694+
1695+
getvvcol(curwin, &curwin->w_cursor,
1696+
NULL, NULL, &vcol);
1697+
++vcol;
1698+
n = vcol;
1699+
}
16691700
ret = regnode(RE_VCOL);
1701+
}
16701702
if (ret == JUST_CALC_SIZE)
16711703
regsize += 5;
16721704
else

src/regexp_nfa.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1707,12 +1707,23 @@ nfa_regatom(void)
17071707
{
17081708
long_u n = 0;
17091709
int cmp = c;
1710+
int cur = FALSE;
17101711

17111712
if (c == '<' || c == '>')
17121713
c = getchr();
1714+
if (no_Magic(c) == '.')
1715+
{
1716+
cur = TRUE;
1717+
c = getchr();
1718+
}
17131719
while (VIM_ISDIGIT(c))
17141720
{
1715-
long_u tmp = n * 10 + (c - '0');
1721+
long_u tmp;
1722+
1723+
if (cur)
1724+
semsg(_(e_regexp_number_after_dot_pos_search),
1725+
no_Magic(c));
1726+
tmp = n * 10 + (c - '0');
17161727

17171728
if (tmp < n)
17181729
{
@@ -1729,18 +1740,35 @@ nfa_regatom(void)
17291740

17301741
if (c == 'l')
17311742
{
1743+
if (cur)
1744+
n = curwin->w_cursor.lnum;
17321745
// \%{n}l \%{n}<l \%{n}>l
17331746
EMIT(cmp == '<' ? NFA_LNUM_LT :
17341747
cmp == '>' ? NFA_LNUM_GT : NFA_LNUM);
17351748
if (save_prev_at_start)
17361749
at_start = TRUE;
17371750
}
17381751
else if (c == 'c')
1752+
{
1753+
if (cur)
1754+
{
1755+
n = curwin->w_cursor.col;
1756+
n++;
1757+
}
17391758
// \%{n}c \%{n}<c \%{n}>c
17401759
EMIT(cmp == '<' ? NFA_COL_LT :
17411760
cmp == '>' ? NFA_COL_GT : NFA_COL);
1761+
}
17421762
else
17431763
{
1764+
if (cur)
1765+
{
1766+
colnr_T vcol = 0;
1767+
1768+
getvvcol(curwin, &curwin->w_cursor,
1769+
NULL, NULL, &vcol);
1770+
n = ++vcol;
1771+
}
17441772
// \%{n}v \%{n}<v \%{n}>v
17451773
EMIT(cmp == '<' ? NFA_VCOL_LT :
17461774
cmp == '>' ? NFA_VCOL_GT : NFA_VCOL);

src/testdir/test_regexp_latin.vim

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,4 +947,94 @@ func Test_regexp_last_subst_string()
947947
close!
948948
endfunc
949949

950+
" Check patterns matching cursor position.
951+
func s:curpos_test2()
952+
new
953+
call setline(1, ['1', '2 foobar eins zwei drei vier fünf sechse',
954+
\ '3 foobar eins zwei drei vier fünf sechse',
955+
\ '4 foobar eins zwei drei vier fünf sechse',
956+
\ '5 foobar eins zwei drei vier fünf sechse',
957+
\ '6 foobar eins zwei drei vier fünf sechse',
958+
\ '7 foobar eins zwei drei vier fünf sechse'])
959+
call setpos('.', [0, 2, 10, 0])
960+
s/\%.c.*//g
961+
call setpos('.', [0, 3, 15, 0])
962+
s/\%.l.*//g
963+
call setpos('.', [0, 5, 3, 0])
964+
s/\%.v.*/_/g
965+
call assert_equal(['1',
966+
\ '2 foobar ',
967+
\ '',
968+
\ '4 foobar eins zwei drei vier fünf sechse',
969+
\ '5 _',
970+
\ '6 foobar eins zwei drei vier fünf sechse',
971+
\ '7 foobar eins zwei drei vier fünf sechse'],
972+
\ getline(1, '$'))
973+
call assert_fails('call search("\\%.1l")', 'E1204:')
974+
call assert_fails('call search("\\%.1c")', 'E1204:')
975+
call assert_fails('call search("\\%.1v")', 'E1204:')
976+
bwipe!
977+
endfunc
978+
979+
" Check patterns matching before or after cursor position.
980+
func s:curpos_test3()
981+
new
982+
call setline(1, ['1', '2 foobar eins zwei drei vier fünf sechse',
983+
\ '3 foobar eins zwei drei vier fünf sechse',
984+
\ '4 foobar eins zwei drei vier fünf sechse',
985+
\ '5 foobar eins zwei drei vier fünf sechse',
986+
\ '6 foobar eins zwei drei vier fünf sechse',
987+
\ '7 foobar eins zwei drei vier fünf sechse'])
988+
call setpos('.', [0, 2, 10, 0])
989+
" Note: This removes all columns, except for the column directly in front of
990+
" the cursor. Bug????
991+
:s/^.*\%<.c//
992+
call setpos('.', [0, 3, 10, 0])
993+
:s/\%>.c.*$//
994+
call setpos('.', [0, 5, 4, 0])
995+
" Note: This removes all columns, except for the column directly in front of
996+
" the cursor. Bug????
997+
:s/^.*\%<.v/_/
998+
call setpos('.', [0, 6, 4, 0])
999+
:s/\%>.v.*$/_/
1000+
call assert_equal(['1',
1001+
\ ' eins zwei drei vier fünf sechse',
1002+
\ '3 foobar e',
1003+
\ '4 foobar eins zwei drei vier fünf sechse',
1004+
\ '_foobar eins zwei drei vier fünf sechse',
1005+
\ '6 fo_',
1006+
\ '7 foobar eins zwei drei vier fünf sechse'],
1007+
\ getline(1, '$'))
1008+
sil %d
1009+
call setline(1, ['1', '2 foobar eins zwei drei vier fünf sechse',
1010+
\ '3 foobar eins zwei drei vier fünf sechse',
1011+
\ '4 foobar eins zwei drei vier fünf sechse',
1012+
\ '5 foobar eins zwei drei vier fünf sechse',
1013+
\ '6 foobar eins zwei drei vier fünf sechse',
1014+
\ '7 foobar eins zwei drei vier fünf sechse'])
1015+
call setpos('.', [0, 4, 4, 0])
1016+
%s/\%<.l.*//
1017+
call setpos('.', [0, 5, 4, 0])
1018+
%s/\%>.l.*//
1019+
call assert_equal(['', '', '',
1020+
\ '4 foobar eins zwei drei vier fünf sechse',
1021+
\ '5 foobar eins zwei drei vier fünf sechse',
1022+
\ '', ''],
1023+
\ getline(1, '$'))
1024+
bwipe!
1025+
endfunc
1026+
1027+
" Test that matching below, at or after the
1028+
" cursor position work
1029+
func Test_matching_pos()
1030+
for val in range(3)
1031+
exe "set re=" .. val
1032+
" Match at cursor position
1033+
call s:curpos_test2()
1034+
" Match before or after cursor position
1035+
call s:curpos_test3()
1036+
endfor
1037+
set re&
1038+
endfunc
1039+
9501040
" vim: shiftwidth=2 sts=2 expandtab

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,8 @@ static char *(features[]) =
755755

756756
static int included_patches[] =
757757
{ /* Add new patch number below this line */
758+
/**/
759+
3110,
758760
/**/
759761
3109,
760762
/**/

0 commit comments

Comments
 (0)