diff options
author | Bram Moolenaar <Bram@vim.org> | 2021-07-05 20:15:23 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-07-05 20:15:23 +0200 |
commit | 04db26b36000a4677b95403ec94bd11f6cc73975 (patch) | |
tree | 409bf4069a07c8276f943b97e8bf93b61c60b01b /src | |
parent | f6d877975ba93fc9b4bee2c5d2aff88dbf9bea59 (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.h | 2 | ||||
-rw-r--r-- | src/regexp_bt.c | 34 | ||||
-rw-r--r-- | src/regexp_nfa.c | 30 | ||||
-rw-r--r-- | src/testdir/test_regexp_latin.vim | 90 | ||||
-rw-r--r-- | src/version.c | 2 |
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, |