diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-03-30 09:03:57 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-30 09:03:57 +0800 |
commit | 75ff156d9b11f23f6156cd6b90fb7bad0a83fd18 (patch) | |
tree | 83c17c86a4bff3b4a703f274202eb59a8b9e3c4d /src | |
parent | e5428d10b5a49e9395190482ff35bbac0c1117ea (diff) | |
parent | 465f8ff8cbd3f9b73c1de8823505ee6a804b2bf1 (diff) | |
download | rneovim-75ff156d9b11f23f6156cd6b90fb7bad0a83fd18.tar.gz rneovim-75ff156d9b11f23f6156cd6b90fb7bad0a83fd18.tar.bz2 rneovim-75ff156d9b11f23f6156cd6b90fb7bad0a83fd18.zip |
Merge pull request #17773 from zeertzjq/vim-8.2.3110
vim-patch:8.2.{3110,4592}: a pattern that matches the cursor position is complicated
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/regexp.c | 6 | ||||
-rw-r--r-- | src/nvim/regexp_bt.c | 28 | ||||
-rw-r--r-- | src/nvim/regexp_nfa.c | 24 | ||||
-rw-r--r-- | src/nvim/testdir/test_regexp_latin.vim | 90 |
4 files changed, 142 insertions, 6 deletions
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 009a26d4e0..d3c43e530a 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -107,8 +107,10 @@ static char_u e_unmatchedpar[] = N_("E55: Unmatched %s)"); static char_u e_z_not_allowed[] = N_("E66: \\z( not allowed here"); static char_u e_z1_not_allowed[] = N_("E67: \\z1 - \\z9 not allowed here"); static char_u e_missing_sb[] = N_("E69: Missing ] after %s%%["); -static char_u e_empty_sb[] = N_("E70: Empty %s%%[]"); -static char_u e_recursive[] = N_("E956: Cannot use pattern recursively"); +static char_u e_empty_sb[] = N_("E70: Empty %s%%[]"); +static char_u e_recursive[] = N_("E956: Cannot use pattern recursively"); +static char_u e_regexp_number_after_dot_pos_search[] + = N_("E1204: No Number allowed after .: '\\%%%c'"); #define NOT_MULTI 0 #define MULTI_ONE 1 diff --git a/src/nvim/regexp_bt.c b/src/nvim/regexp_bt.c index 3835a2bbae..7d0b9a7a77 100644 --- a/src/nvim/regexp_bt.c +++ b/src/nvim/regexp_bt.c @@ -1578,14 +1578,19 @@ static char_u *regatom(int *flagp) } default: - if (ascii_isdigit(c) || c == '<' || c == '>' - || c == '\'') { + if (ascii_isdigit(c) || c == '<' || c == '>' || c == '\'' || c == '.') { uint32_t n = 0; int cmp; + bool cur = false; cmp = c; - if (cmp == '<' || cmp == '>') + if (cmp == '<' || cmp == '>') { c = getchr(); + } + if (no_Magic(c) == '.') { + cur = true; + c = getchr(); + } while (ascii_isdigit(c)) { n = n * 10 + (uint32_t)(c - '0'); c = getchr(); @@ -1602,14 +1607,31 @@ static char_u *regatom(int *flagp) } break; } 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); + n = ++vcol; + } ret = regnode(RE_VCOL); } if (ret == JUST_CALC_SIZE) { diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index 7e316624f8..8a14a2864c 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -1639,10 +1639,20 @@ static int nfa_regatom(void) { int64_t n = 0; const int cmp = c; + bool cur = false; - if (c == '<' || c == '>') + if (c == '<' || c == '>') { c = getchr(); + } + if (no_Magic(c) == '.') { + cur = true; + c = getchr(); + } while (ascii_isdigit(c)) { + if (cur) { + semsg(_(e_regexp_number_after_dot_pos_search), no_Magic(c)); + return FAIL; + } if (n > (INT32_MAX - (c - '0')) / 10) { // overflow. emsg(_(e_value_too_large)); @@ -1655,6 +1665,9 @@ static int nfa_regatom(void) int32_t limit = INT32_MAX; 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); @@ -1662,10 +1675,19 @@ static int 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/nvim/testdir/test_regexp_latin.vim b/src/nvim/testdir/test_regexp_latin.vim index cbd45696a9..b733e334de 100644 --- a/src/nvim/testdir/test_regexp_latin.vim +++ b/src/nvim/testdir/test_regexp_latin.vim @@ -787,6 +787,96 @@ func Test_regexp_error() set re& 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 + func Test_using_mark_position() " this was using freed memory " new engine |