diff options
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 | 
