mirror of
https://github.com/neovim/neovim.git
synced 2025-09-14 15:28:17 +00:00
vim-patch:7.4.984
Problem: searchpos() always starts searching in the first column, which is
not what some people expect. (Brett Stahlman)
Solution: Add the 'z' flag: start at the specified column.
ad4d8a192a
This commit is contained in:
@@ -5447,14 +5447,15 @@ search({pattern} [, {flags} [, {stopline} [, {timeout}]]]) *search()*
|
|||||||
move. No error message is given.
|
move. No error message is given.
|
||||||
|
|
||||||
{flags} is a String, which can contain these character flags:
|
{flags} is a String, which can contain these character flags:
|
||||||
'b' search backward instead of forward
|
'b' search Backward instead of forward
|
||||||
'c' accept a match at the cursor position
|
'c' accept a match at the Cursor position
|
||||||
'e' move to the End of the match
|
'e' move to the End of the match
|
||||||
'n' do Not move the cursor
|
'n' do Not move the cursor
|
||||||
'p' return number of matching sub-pattern (see below)
|
'p' return number of matching sub-Pattern (see below)
|
||||||
's' set the ' mark at the previous location of the cursor
|
's' Set the ' mark at the previous location of the cursor
|
||||||
'w' wrap around the end of the file
|
'w' Wrap around the end of the file
|
||||||
'W' don't wrap around the end of the file
|
'W' don't Wrap around the end of the file
|
||||||
|
'z' start searching at the cursor column instead of Zero
|
||||||
If neither 'w' or 'W' is given, the 'wrapscan' option applies.
|
If neither 'w' or 'W' is given, the 'wrapscan' option applies.
|
||||||
|
|
||||||
If the 's' flag is supplied, the ' mark is set, only if the
|
If the 's' flag is supplied, the ' mark is set, only if the
|
||||||
@@ -5462,6 +5463,12 @@ search({pattern} [, {flags} [, {stopline} [, {timeout}]]]) *search()*
|
|||||||
flag.
|
flag.
|
||||||
|
|
||||||
'ignorecase', 'smartcase' and 'magic' are used.
|
'ignorecase', 'smartcase' and 'magic' are used.
|
||||||
|
|
||||||
|
When the 'z' flag is not given seaching always starts in
|
||||||
|
column zero and then matches before the cursor are skipped.
|
||||||
|
When the 'c' flag is present in 'cpo' the next search starts
|
||||||
|
after the match. Without the 'c' flag the next search starts
|
||||||
|
one column further.
|
||||||
|
|
||||||
When the {stopline} argument is given then the search stops
|
When the {stopline} argument is given then the search stops
|
||||||
after searching this line. This is useful to restrict the
|
after searching this line. This is useful to restrict the
|
||||||
|
@@ -14345,14 +14345,14 @@ static void f_reverse(typval_T *argvars, typval_T *rettv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SP_NOMOVE 0x01 /* don't move cursor */
|
#define SP_NOMOVE 0x01 ///< don't move cursor
|
||||||
#define SP_REPEAT 0x02 /* repeat to find outer pair */
|
#define SP_REPEAT 0x02 ///< repeat to find outer pair
|
||||||
#define SP_RETCOUNT 0x04 /* return matchcount */
|
#define SP_RETCOUNT 0x04 ///< return matchcount
|
||||||
#define SP_SETPCMARK 0x08 /* set previous context mark */
|
#define SP_SETPCMARK 0x08 ///< set previous context mark
|
||||||
#define SP_START 0x10 /* accept match at start position */
|
#define SP_START 0x10 ///< accept match at start position
|
||||||
#define SP_SUBPAT 0x20 /* return nr of matching sub-pattern */
|
#define SP_SUBPAT 0x20 ///< return nr of matching sub-pattern
|
||||||
#define SP_END 0x40 /* leave cursor at end of match */
|
#define SP_END 0x40 ///< leave cursor at end of match
|
||||||
|
#define SP_COLUMN 0x80 ///< start at cursor column
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get flags for a search function.
|
* Get flags for a search function.
|
||||||
@@ -14378,13 +14378,14 @@ static int get_search_arg(typval_T *varp, int *flagsp)
|
|||||||
default: mask = 0;
|
default: mask = 0;
|
||||||
if (flagsp != NULL)
|
if (flagsp != NULL)
|
||||||
switch (*flags) {
|
switch (*flags) {
|
||||||
case 'c': mask = SP_START; break;
|
case 'c': mask = SP_START; break;
|
||||||
case 'e': mask = SP_END; break;
|
case 'e': mask = SP_END; break;
|
||||||
case 'm': mask = SP_RETCOUNT; break;
|
case 'm': mask = SP_RETCOUNT; break;
|
||||||
case 'n': mask = SP_NOMOVE; break;
|
case 'n': mask = SP_NOMOVE; break;
|
||||||
case 'p': mask = SP_SUBPAT; break;
|
case 'p': mask = SP_SUBPAT; break;
|
||||||
case 'r': mask = SP_REPEAT; break;
|
case 'r': mask = SP_REPEAT; break;
|
||||||
case 's': mask = SP_SETPCMARK; break;
|
case 's': mask = SP_SETPCMARK; break;
|
||||||
|
case 'z': mask = SP_COLUMN; break;
|
||||||
}
|
}
|
||||||
if (mask == 0) {
|
if (mask == 0) {
|
||||||
EMSG2(_(e_invarg2), flags);
|
EMSG2(_(e_invarg2), flags);
|
||||||
@@ -14400,9 +14401,7 @@ static int get_search_arg(typval_T *varp, int *flagsp)
|
|||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Shared by search() and searchpos() functions.
|
||||||
* Shared by search() and searchpos() functions
|
|
||||||
*/
|
|
||||||
static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
|
static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
@@ -14423,10 +14422,15 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
|
|||||||
if (dir == 0)
|
if (dir == 0)
|
||||||
goto theend;
|
goto theend;
|
||||||
flags = *flagsp;
|
flags = *flagsp;
|
||||||
if (flags & SP_START)
|
if (flags & SP_START) {
|
||||||
options |= SEARCH_START;
|
options |= SEARCH_START;
|
||||||
if (flags & SP_END)
|
}
|
||||||
|
if (flags & SP_END) {
|
||||||
options |= SEARCH_END;
|
options |= SEARCH_END;
|
||||||
|
}
|
||||||
|
if (flags & SP_COLUMN) {
|
||||||
|
options |= SEARCH_COL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Optional arguments: line number to stop searching and timeout. */
|
/* Optional arguments: line number to stop searching and timeout. */
|
||||||
if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) {
|
if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) {
|
||||||
|
@@ -453,25 +453,24 @@ void last_pat_prog(regmmatch_T *regmatch)
|
|||||||
--emsg_off;
|
--emsg_off;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// lowest level search function.
|
||||||
* lowest level search function.
|
/// Search for 'count'th occurrence of pattern 'pat' in direction 'dir'.
|
||||||
* Search for 'count'th occurrence of pattern 'pat' in direction 'dir'.
|
/// Start at position 'pos' and return the found position in 'pos'.
|
||||||
* Start at position 'pos' and return the found position in 'pos'.
|
///
|
||||||
*
|
/// if (options & SEARCH_MSG) == 0 don't give any messages
|
||||||
* if (options & SEARCH_MSG) == 0 don't give any messages
|
/// if (options & SEARCH_MSG) == SEARCH_NFMSG don't give 'notfound' messages
|
||||||
* if (options & SEARCH_MSG) == SEARCH_NFMSG don't give 'notfound' messages
|
/// if (options & SEARCH_MSG) == SEARCH_MSG give all messages
|
||||||
* if (options & SEARCH_MSG) == SEARCH_MSG give all messages
|
/// if (options & SEARCH_HIS) put search pattern in history
|
||||||
* if (options & SEARCH_HIS) put search pattern in history
|
/// if (options & SEARCH_END) return position at end of match
|
||||||
* if (options & SEARCH_END) return position at end of match
|
/// if (options & SEARCH_START) accept match at pos itself
|
||||||
* if (options & SEARCH_START) accept match at pos itself
|
/// if (options & SEARCH_KEEP) keep previous search pattern
|
||||||
* if (options & SEARCH_KEEP) keep previous search pattern
|
/// if (options & SEARCH_FOLD) match only once in a closed fold
|
||||||
* if (options & SEARCH_FOLD) match only once in a closed fold
|
/// if (options & SEARCH_PEEK) check for typed char, cancel search
|
||||||
* if (options & SEARCH_PEEK) check for typed char, cancel search
|
/// if (options & SEARCH_COL) start at pos->col instead of zero
|
||||||
*
|
///
|
||||||
* Return FAIL (zero) for failure, non-zero for success.
|
/// @returns FAIL (zero) for failure, non-zero for success.
|
||||||
* Returns the index of the first matching
|
/// the index of the first matching
|
||||||
* subpattern plus one; one if there was none.
|
/// subpattern plus one; one if there was none.
|
||||||
*/
|
|
||||||
int searchit(
|
int searchit(
|
||||||
win_T *win, /* window to search in, can be NULL for a
|
win_T *win, /* window to search in, can be NULL for a
|
||||||
buffer without a window! */
|
buffer without a window! */
|
||||||
@@ -571,16 +570,14 @@ int searchit(
|
|||||||
if (tm != NULL && profile_passed_limit(*tm))
|
if (tm != NULL && profile_passed_limit(*tm))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
// Look for a match somewhere in line "lnum".
|
||||||
* Look for a match somewhere in line "lnum".
|
colnr_T col = at_first_line && (options & SEARCH_COL) ? pos->col : 0;
|
||||||
*/
|
|
||||||
nmatched = vim_regexec_multi(®match, win, buf,
|
nmatched = vim_regexec_multi(®match, win, buf,
|
||||||
lnum, (colnr_T)0,
|
lnum, col, tm);
|
||||||
tm
|
// Abort searching on an error (e.g., out of stack).
|
||||||
);
|
if (called_emsg) {
|
||||||
/* Abort searching on an error (e.g., out of stack). */
|
|
||||||
if (called_emsg)
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
if (nmatched > 0) {
|
if (nmatched > 0) {
|
||||||
/* match may actually be in another line when using \zs */
|
/* match may actually be in another line when using \zs */
|
||||||
matchpos = regmatch.startpos[0];
|
matchpos = regmatch.startpos[0];
|
||||||
@@ -881,9 +878,8 @@ static void set_vv_searchforward(void)
|
|||||||
set_vim_var_nr(VV_SEARCHFORWARD, (long)(spats[0].off.dir == '/'));
|
set_vim_var_nr(VV_SEARCHFORWARD, (long)(spats[0].off.dir == '/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Return the number of the first subpat that matched.
|
||||||
* Return the number of the first subpat that matched.
|
// Return zero if none of them matched.
|
||||||
*/
|
|
||||||
static int first_submatch(regmmatch_T *rp)
|
static int first_submatch(regmmatch_T *rp)
|
||||||
{
|
{
|
||||||
int submatch;
|
int submatch;
|
||||||
|
@@ -15,19 +15,20 @@
|
|||||||
#define ACTION_SHOW_ALL 4
|
#define ACTION_SHOW_ALL 4
|
||||||
#define ACTION_EXPAND 5
|
#define ACTION_EXPAND 5
|
||||||
|
|
||||||
/* Values for 'options' argument in do_search() and searchit() */
|
// Values for 'options' argument in do_search() and searchit()
|
||||||
#define SEARCH_REV 0x01 /* go in reverse of previous dir. */
|
#define SEARCH_REV 0x01 ///< go in reverse of previous dir.
|
||||||
#define SEARCH_ECHO 0x02 /* echo the search command and handle options */
|
#define SEARCH_ECHO 0x02 ///< echo the search command and handle options
|
||||||
#define SEARCH_MSG 0x0c /* give messages (yes, it's not 0x04) */
|
#define SEARCH_MSG 0x0c ///< give messages (yes, it's not 0x04)
|
||||||
#define SEARCH_NFMSG 0x08 /* give all messages except not found */
|
#define SEARCH_NFMSG 0x08 ///< give all messages except not found
|
||||||
#define SEARCH_OPT 0x10 /* interpret optional flags */
|
#define SEARCH_OPT 0x10 ///< interpret optional flags
|
||||||
#define SEARCH_HIS 0x20 /* put search pattern in history */
|
#define SEARCH_HIS 0x20 ///< put search pattern in history
|
||||||
#define SEARCH_END 0x40 /* put cursor at end of match */
|
#define SEARCH_END 0x40 ///< put cursor at end of match
|
||||||
#define SEARCH_NOOF 0x80 /* don't add offset to position */
|
#define SEARCH_NOOF 0x80 ///< don't add offset to position
|
||||||
#define SEARCH_START 0x100 /* start search without col offset */
|
#define SEARCH_START 0x100 ///< start search without col offset
|
||||||
#define SEARCH_MARK 0x200 /* set previous context mark */
|
#define SEARCH_MARK 0x200 ///< set previous context mark
|
||||||
#define SEARCH_KEEP 0x400 /* keep previous search pattern */
|
#define SEARCH_KEEP 0x400 ///< keep previous search pattern
|
||||||
#define SEARCH_PEEK 0x800 /* peek for typed char, cancel search */
|
#define SEARCH_PEEK 0x800 ///< peek for typed char, cancel search
|
||||||
|
#define SEARCH_COL 0x1000 ///< start at specified column instead of zero
|
||||||
|
|
||||||
/* Values for flags argument for findmatchlimit() */
|
/* Values for flags argument for findmatchlimit() */
|
||||||
#define FM_BACKWARD 0x01 /* search backwards */
|
#define FM_BACKWARD 0x01 /* search backwards */
|
||||||
|
28
src/nvim/testdir/test_searchpos.vim
Normal file
28
src/nvim/testdir/test_searchpos.vim
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
" Tests for searchpos()
|
||||||
|
|
||||||
|
func Test_searchpos()
|
||||||
|
new one
|
||||||
|
0put ='1a3'
|
||||||
|
1put ='123xyz'
|
||||||
|
call cursor(1, 1)
|
||||||
|
call assert_equal([1, 1, 2], searchpos('\%(\([a-z]\)\|\_.\)\{-}xyz', 'pcW'))
|
||||||
|
call cursor(1, 2)
|
||||||
|
call assert_equal([2, 1, 1], searchpos('\%(\([a-z]\)\|\_.\)\{-}xyz', 'pcW'))
|
||||||
|
set cpo-=c
|
||||||
|
call cursor(1, 2)
|
||||||
|
call assert_equal([1, 2, 2], searchpos('\%(\([a-z]\)\|\_.\)\{-}xyz', 'pcW'))
|
||||||
|
call cursor(1, 3)
|
||||||
|
call assert_equal([1, 3, 1], searchpos('\%(\([a-z]\)\|\_.\)\{-}xyz', 'pcW'))
|
||||||
|
|
||||||
|
" Now with \zs, first match is in column 0, "a" is matched.
|
||||||
|
call cursor(1. 3)
|
||||||
|
call assert_equal([2, 4, 2], searchpos('\%(\([a-z]\)\|\_.\)\{-}\zsxyz', 'pcW'))
|
||||||
|
" With z flag start at cursor column, don't see the "a".
|
||||||
|
call cursor(1. 3)
|
||||||
|
call assert_equal([2, 4, 1], searchpos('\%(\([a-z]\)\|\_.\)\{-}\zsxyz', 'pcWz'))
|
||||||
|
|
||||||
|
set cpo+=c
|
||||||
|
" close the window
|
||||||
|
q!
|
||||||
|
|
||||||
|
endfunc
|
@@ -306,7 +306,7 @@ static int included_patches[] = {
|
|||||||
// 987 NA
|
// 987 NA
|
||||||
// 986 NA
|
// 986 NA
|
||||||
// 985 NA
|
// 985 NA
|
||||||
// 984,
|
984,
|
||||||
// 983,
|
// 983,
|
||||||
// 982 NA
|
// 982 NA
|
||||||
981,
|
981,
|
||||||
|
Reference in New Issue
Block a user