mirror of
https://github.com/neovim/neovim.git
synced 2024-12-31 17:13:26 -07:00
vim-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 vim/vim#8497, closes vim/vim#8179)
04db26b360
Also use `n = ++vcol` in regexp_bt.c as `++vcol` alone fails lint.
This commit is contained in:
parent
e5428d10b5
commit
1bbe8ec282
@ -918,13 +918,20 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on):
|
||||
\%23l Matches in a specific line.
|
||||
\%<23l Matches above a specific line (lower line number).
|
||||
\%>23l Matches below a specific line (higher line number).
|
||||
\%.l Matches at the cursor line.
|
||||
\%<.l Matches above the cursor line.
|
||||
\%>.l Matches below the cursor line.
|
||||
These three can be used to match specific lines in a buffer. The "23"
|
||||
can be any line number. The first line is 1.
|
||||
WARNING: When inserting or deleting lines Vim does not automatically
|
||||
update the matches. This means Syntax highlighting quickly becomes
|
||||
wrong.
|
||||
wrong. Also when refering to the cursor position (".") and
|
||||
the cursor moves the display isn't updated for this change. An update
|
||||
is done when using the |CTRL-L| command (the whole screen is updated).
|
||||
Example, to highlight the line where the cursor currently is: >
|
||||
:exe '/\%' .. line(".") .. 'l.*'
|
||||
:exe '/\%' .. line(".") .. 'l'
|
||||
< Alternatively use: >
|
||||
/\%.l
|
||||
< When 'hlsearch' is set and you move the cursor around and make changes
|
||||
this will clearly show when the match is updated or not.
|
||||
|
||||
@ -932,15 +939,23 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on):
|
||||
\%23c Matches in a specific column.
|
||||
\%<23c Matches before a specific column.
|
||||
\%>23c Matches after a specific column.
|
||||
\%.c Matches at the cursor column.
|
||||
\%<.c Matches before the cursor column.
|
||||
\%>.c Matches after the cursor column.
|
||||
These three can be used to match specific columns in a buffer or
|
||||
string. The "23" can be any column number. The first column is 1.
|
||||
Actually, the column is the byte number (thus it's not exactly right
|
||||
for multibyte characters).
|
||||
WARNING: When inserting or deleting text Vim does not automatically
|
||||
update the matches. This means Syntax highlighting quickly becomes
|
||||
wrong.
|
||||
wrong. Also when refering to the cursor position (".") and
|
||||
the cursor moves the display isn't updated for this change. An update
|
||||
is done when using the |CTRL-L| command (the whole screen is updated).
|
||||
|
||||
Example, to highlight the column where the cursor currently is: >
|
||||
:exe '/\%' .. col(".") .. 'c'
|
||||
< Alternatively use: >
|
||||
/\%.c
|
||||
< When 'hlsearch' is set and you move the cursor around and make changes
|
||||
this will clearly show when the match is updated or not.
|
||||
Example for matching a single byte in column 44: >
|
||||
@ -951,6 +966,9 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on):
|
||||
\%23v Matches in a specific virtual column.
|
||||
\%<23v Matches before a specific virtual column.
|
||||
\%>23v Matches after a specific virtual column.
|
||||
\%.v Matches at the current virtual column.
|
||||
\%<.v Matches before the current virtual column.
|
||||
\%>.v Matches after the current virtual column.
|
||||
These three can be used to match specific virtual columns in a buffer
|
||||
or string. When not matching with a buffer in a window, the option
|
||||
values of the current window are used (e.g., 'tabstop').
|
||||
@ -960,13 +978,18 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on):
|
||||
one screen character.
|
||||
WARNING: When inserting or deleting text Vim does not automatically
|
||||
update highlighted matches. This means Syntax highlighting quickly
|
||||
becomes wrong.
|
||||
becomes wrong. Also when refering to the cursor position (".") and
|
||||
the cursor moves the display isn't updated for this change. An update
|
||||
is done when using the |CTRL-L| command (the whole screen is updated).
|
||||
Example, to highlight all the characters after virtual column 72: >
|
||||
/\%>72v.*
|
||||
< When 'hlsearch' is set and you move the cursor around and make changes
|
||||
this will clearly show when the match is updated or not.
|
||||
To match the text up to column 17: >
|
||||
/^.*\%17v
|
||||
< To match all characters after the current virtual column (where the
|
||||
cursor is): >
|
||||
/\%>.v.*
|
||||
< Column 17 is not included, because this is a |/zero-width| match. To
|
||||
include the column use: >
|
||||
/^.*\%17v.
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -1639,10 +1639,19 @@ 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));
|
||||
}
|
||||
if (n > (INT32_MAX - (c - '0')) / 10) {
|
||||
// overflow.
|
||||
emsg(_(e_value_too_large));
|
||||
@ -1655,6 +1664,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 +1674,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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user