summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-07-05 20:15:23 +0200
committerBram Moolenaar <Bram@vim.org>2021-07-05 20:15:23 +0200
commit04db26b36000a4677b95403ec94bd11f6cc73975 (patch)
tree409bf4069a07c8276f943b97e8bf93b61c60b01b /src
parentf6d877975ba93fc9b4bee2c5d2aff88dbf9bea59 (diff)
patch 8.2.3110: a pattern that matches the cursor position is complicatedv8.2.3110
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)
Diffstat (limited to 'src')
-rw-r--r--src/errors.h2
-rw-r--r--src/regexp_bt.c34
-rw-r--r--src/regexp_nfa.c30
-rw-r--r--src/testdir/test_regexp_latin.vim90
-rw-r--r--src/version.c2
5 files changed, 156 insertions, 2 deletions
diff --git a/src/errors.h b/src/errors.h
index f2624dfc1d..7524b80468 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -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'"));
diff --git a/src/regexp_bt.c b/src/regexp_bt.c
index 70ddfe986f..dae6d519be 100644
--- a/src/regexp_bt.c
+++ b/src/regexp_bt.c
@@ -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
diff --git a/src/regexp_nfa.c b/src/regexp_nfa.c
index 2ed18685d9..7dff195ea2 100644
--- a/src/regexp_nfa.c
+++ b/src/regexp_nfa.c
@@ -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);
diff --git a/src/testdir/test_regexp_latin.vim b/src/testdir/test_regexp_latin.vim
index e53a8da588..c487b274d2 100644
--- a/src/testdir/test_regexp_latin.vim
+++ b/src/testdir/test_regexp_latin.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index a36ec80cf4..b448822d5a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -756,6 +756,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 3110,
+/**/
3109,
/**/
3108,