mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #3203 from jamessan/vim-7.4.813
Add getcharsearch() and setcharsearch()
This commit is contained in:
commit
f253c8d9b4
@ -1967,6 +1967,7 @@ server2client( {clientid}, {string})
|
||||
Number send reply string
|
||||
serverlist() String get a list of available servers
|
||||
setbufvar( {expr}, {varname}, {val}) set {varname} in buffer {expr} to {val}
|
||||
setcharsearch( {dict}) Dict set character search from {dict}
|
||||
setcmdpos( {pos}) Number set cursor position in command-line
|
||||
setline( {lnum}, {line}) Number set line {lnum} to {line}
|
||||
setloclist( {nr}, {list}[, {action}])
|
||||
@ -3339,6 +3340,26 @@ getcharmod() *getcharmod()*
|
||||
character itself are obtained. Thus Shift-a results in "A"
|
||||
without a modifier.
|
||||
|
||||
getcharsearch() *getcharsearch()*
|
||||
Return the current character search information as a {dict}
|
||||
with the following entries:
|
||||
|
||||
char character previously used for a character
|
||||
search (|t|, |f|, |T|, or |F|); empty string
|
||||
if no character search has been performed
|
||||
forward direction of character search; 1 for forward,
|
||||
0 for backward
|
||||
until type of character search; 1 for a |t| or |T|
|
||||
character search, 0 for an |f| or |F|
|
||||
character search
|
||||
|
||||
This can be useful to always have |;| and |,| search
|
||||
forward/backward regardless of the direction of the previous
|
||||
character search: >
|
||||
:nnoremap <expr> ; getcharsearch().forward ? ';' : ','
|
||||
:nnoremap <expr> , getcharsearch().forward ? ',' : ';'
|
||||
< Also see |setcharsearch()|.
|
||||
|
||||
getcmdline() *getcmdline()*
|
||||
Return the current command-line. Only works when the command
|
||||
line is being edited, thus requires use of |c_CTRL-\_e| or
|
||||
@ -5531,6 +5552,26 @@ setbufvar({expr}, {varname}, {val}) *setbufvar()*
|
||||
:call setbufvar("todo", "myvar", "foobar")
|
||||
< This function is not available in the |sandbox|.
|
||||
|
||||
setcharsearch() *setcharsearch()*
|
||||
Set the current character search information to {dict},
|
||||
which contains one or more of the following entries:
|
||||
|
||||
char character which will be used for a subsequent
|
||||
|,| or |;| command; an empty string clears the
|
||||
character search
|
||||
forward direction of character search; 1 for forward,
|
||||
0 for backward
|
||||
until type of character search; 1 for a |t| or |T|
|
||||
character search, 0 for an |f| or |F|
|
||||
character search
|
||||
|
||||
This can be useful to save/restore a user's character search
|
||||
from a script: >
|
||||
:let prevsearch = getcharsearch()
|
||||
:" Perform a command which clobbers user's search
|
||||
:call setcharsearch(prevsearch)
|
||||
< Also see |getcharsearch()|.
|
||||
|
||||
setcmdpos({pos}) *setcmdpos()*
|
||||
Set the cursor position in the command line to byte position
|
||||
{pos}. The first position is 1.
|
||||
|
@ -6599,6 +6599,7 @@ static struct fst {
|
||||
{"getbufvar", 2, 3, f_getbufvar},
|
||||
{"getchar", 0, 1, f_getchar},
|
||||
{"getcharmod", 0, 0, f_getcharmod},
|
||||
{"getcharsearch", 0, 0, f_getcharsearch},
|
||||
{"getcmdline", 0, 0, f_getcmdline},
|
||||
{"getcmdpos", 0, 0, f_getcmdpos},
|
||||
{"getcmdtype", 0, 0, f_getcmdtype},
|
||||
@ -6725,6 +6726,7 @@ static struct fst {
|
||||
{"serverstart", 0, 1, f_serverstart},
|
||||
{"serverstop", 1, 1, f_serverstop},
|
||||
{"setbufvar", 3, 3, f_setbufvar},
|
||||
{"setcharsearch", 1, 1, f_setcharsearch},
|
||||
{"setcmdpos", 1, 1, f_setcmdpos},
|
||||
{"setline", 2, 2, f_setline},
|
||||
{"setloclist", 2, 3, f_setloclist},
|
||||
@ -9303,6 +9305,20 @@ static void f_getcharmod(typval_T *argvars, typval_T *rettv)
|
||||
rettv->vval.v_number = mod_mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* "getcharsearch()" function
|
||||
*/
|
||||
static void f_getcharsearch(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
rettv_dict_alloc(rettv);
|
||||
|
||||
dict_T *dict = rettv->vval.v_dict;
|
||||
|
||||
dict_add_nr_str(dict, "char", 0L, last_csearch());
|
||||
dict_add_nr_str(dict, "forward", last_csearch_forward(), NULL);
|
||||
dict_add_nr_str(dict, "until", last_csearch_until(), NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* "getcmdline()" function
|
||||
*/
|
||||
@ -14299,6 +14315,40 @@ static void f_setbufvar(typval_T *argvars, typval_T *rettv)
|
||||
}
|
||||
}
|
||||
|
||||
static void f_setcharsearch(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
dict_T *d;
|
||||
dictitem_T *di;
|
||||
char_u *csearch;
|
||||
|
||||
if (argvars[0].v_type != VAR_DICT) {
|
||||
EMSG(_(e_dictreq));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((d = argvars[0].vval.v_dict) != NULL) {
|
||||
csearch = get_dict_string(d, (char_u *)"char", FALSE);
|
||||
if (csearch != NULL) {
|
||||
if (enc_utf8) {
|
||||
int pcc[MAX_MCO];
|
||||
int c = utfc_ptr2char(csearch, pcc);
|
||||
set_last_csearch(c, csearch, utfc_ptr2len(csearch));
|
||||
}
|
||||
else
|
||||
set_last_csearch(PTR2CHAR(csearch),
|
||||
csearch, MB_PTR2LEN(csearch));
|
||||
}
|
||||
|
||||
di = dict_find(d, (char_u *)"forward", -1);
|
||||
if (di != NULL)
|
||||
set_csearch_direction(get_tv_number(&di->di_tv) ? FORWARD : BACKWARD);
|
||||
|
||||
di = dict_find(d, (char_u *)"until", -1);
|
||||
if (di != NULL)
|
||||
set_csearch_until(!!get_tv_number(&di->di_tv));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "setcmdpos()" function
|
||||
*/
|
||||
|
@ -108,6 +108,12 @@ static struct spat spats[2] =
|
||||
|
||||
static int last_idx = 0; /* index in spats[] for RE_LAST */
|
||||
|
||||
static char_u lastc[2] = {NUL, NUL}; /* last character searched for */
|
||||
static int lastcdir = FORWARD; /* last direction of character search */
|
||||
static int last_t_cmd = TRUE; /* last search t_cmd */
|
||||
static char_u lastc_bytes[MB_MAXBYTES + 1];
|
||||
static int lastc_bytelen = 1; /* >1 for multi-byte char */
|
||||
|
||||
/* copy of spats[], for keeping the search patterns while executing autocmds */
|
||||
static struct spat saved_spats[2];
|
||||
static int saved_last_idx = 0;
|
||||
@ -327,7 +333,7 @@ int ignorecase(char_u *pat)
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if patter "pat" has an uppercase character.
|
||||
* Return TRUE if pattern "pat" has an uppercase character.
|
||||
*/
|
||||
int pat_has_uppercase(char_u *pat)
|
||||
{
|
||||
@ -357,6 +363,41 @@ int pat_has_uppercase(char_u *pat)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
char_u *last_csearch(void)
|
||||
{
|
||||
return lastc_bytes;
|
||||
}
|
||||
|
||||
int last_csearch_forward(void)
|
||||
{
|
||||
return lastcdir == FORWARD;
|
||||
}
|
||||
|
||||
int last_csearch_until(void)
|
||||
{
|
||||
return last_t_cmd == TRUE;
|
||||
}
|
||||
|
||||
void set_last_csearch(int c, char_u *s, int len)
|
||||
{
|
||||
*lastc = c;
|
||||
lastc_bytelen = len;
|
||||
if (len)
|
||||
memcpy(lastc_bytes, s, len);
|
||||
else
|
||||
memset(lastc_bytes, 0, sizeof(lastc_bytes));
|
||||
}
|
||||
|
||||
void set_csearch_direction(int cdir)
|
||||
{
|
||||
lastcdir = cdir;
|
||||
}
|
||||
|
||||
void set_csearch_until(int t_cmd)
|
||||
{
|
||||
last_t_cmd = t_cmd;
|
||||
}
|
||||
|
||||
char_u *last_search_pat(void)
|
||||
{
|
||||
return spats[last_idx].pat;
|
||||
@ -1286,38 +1327,33 @@ int searchc(cmdarg_T *cap, int t_cmd)
|
||||
int c = cap->nchar; /* char to search for */
|
||||
int dir = cap->arg; /* TRUE for searching forward */
|
||||
long count = cap->count1; /* repeat count */
|
||||
static int lastc = NUL; /* last character searched for */
|
||||
static int lastcdir; /* last direction of character search */
|
||||
static int last_t_cmd; /* last search t_cmd */
|
||||
int col;
|
||||
char_u *p;
|
||||
int len;
|
||||
int stop = TRUE;
|
||||
static char_u bytes[MB_MAXBYTES + 1];
|
||||
static int bytelen = 1; /* >1 for multi-byte char */
|
||||
|
||||
if (c != NUL) { /* normal search: remember args for repeat */
|
||||
if (!KeyStuffed) { /* don't remember when redoing */
|
||||
lastc = c;
|
||||
lastcdir = dir;
|
||||
last_t_cmd = t_cmd;
|
||||
bytelen = (*mb_char2bytes)(c, bytes);
|
||||
*lastc = c;
|
||||
set_csearch_direction(dir);
|
||||
set_csearch_until(t_cmd);
|
||||
lastc_bytelen = (*mb_char2bytes)(c, lastc_bytes);
|
||||
if (cap->ncharC1 != 0) {
|
||||
bytelen += (*mb_char2bytes)(cap->ncharC1, bytes + bytelen);
|
||||
lastc_bytelen += (*mb_char2bytes)(cap->ncharC1, lastc_bytes + lastc_bytelen);
|
||||
if (cap->ncharC2 != 0)
|
||||
bytelen += (*mb_char2bytes)(cap->ncharC2, bytes + bytelen);
|
||||
lastc_bytelen += (*mb_char2bytes)(cap->ncharC2, lastc_bytes + lastc_bytelen);
|
||||
}
|
||||
}
|
||||
} else { /* repeat previous search */
|
||||
if (lastc == NUL)
|
||||
if (*lastc == NUL)
|
||||
return FAIL;
|
||||
if (dir) /* repeat in opposite direction */
|
||||
dir = -lastcdir;
|
||||
else
|
||||
dir = lastcdir;
|
||||
t_cmd = last_t_cmd;
|
||||
c = lastc;
|
||||
/* For multi-byte re-use last bytes[] and bytelen. */
|
||||
c = *lastc;
|
||||
/* For multi-byte re-use last lastc_bytes[] and lastc_bytelen. */
|
||||
|
||||
/* Force a move of at least one char, so ";" and "," will move the
|
||||
* cursor, even if the cursor is right in front of char we are looking
|
||||
@ -1347,11 +1383,11 @@ int searchc(cmdarg_T *cap, int t_cmd)
|
||||
return FAIL;
|
||||
col -= (*mb_head_off)(p, p + col - 1) + 1;
|
||||
}
|
||||
if (bytelen == 1) {
|
||||
if (lastc_bytelen == 1) {
|
||||
if (p[col] == c && stop)
|
||||
break;
|
||||
} else {
|
||||
if (memcmp(p + col, bytes, bytelen) == 0 && stop)
|
||||
if (memcmp(p + col, lastc_bytes, lastc_bytelen) == 0 && stop)
|
||||
break;
|
||||
}
|
||||
stop = TRUE;
|
||||
@ -1372,8 +1408,8 @@ int searchc(cmdarg_T *cap, int t_cmd)
|
||||
col -= dir;
|
||||
if (has_mbyte) {
|
||||
if (dir < 0)
|
||||
/* Landed on the search char which is bytelen long */
|
||||
col += bytelen - 1;
|
||||
/* Landed on the search char which is lastc_bytelen long */
|
||||
col += lastc_bytelen - 1;
|
||||
else
|
||||
/* To previous char, which may be multi-byte. */
|
||||
col -= (*mb_head_off)(p, p + col);
|
||||
|
@ -27,6 +27,7 @@ SCRIPTS := test_eval.out \
|
||||
test88.out \
|
||||
test_listlbr.out \
|
||||
test_breakindent.out \
|
||||
test_charsearch.out \
|
||||
test_close_count.out \
|
||||
test_command_count.out \
|
||||
|
||||
|
25
src/nvim/testdir/test_charsearch.in
Normal file
25
src/nvim/testdir/test_charsearch.in
Normal file
@ -0,0 +1,25 @@
|
||||
Test for character searches
|
||||
|
||||
STARTTEST
|
||||
:so small.vim
|
||||
:" check that "fe" and ";" work
|
||||
/^X
|
||||
ylfep;;p,,p:
|
||||
:" check that save/restore works
|
||||
/^Y
|
||||
ylfep:let csave = getcharsearch()
|
||||
fip:call setcharsearch(csave)
|
||||
;p;p:
|
||||
:" check that setcharsearch() changes the settins.
|
||||
/^Z
|
||||
ylfep:call setcharsearch({'char': 'k'})
|
||||
;p:call setcharsearch({'forward': 0})
|
||||
$;p:call setcharseearch({'until'}: 1})
|
||||
;;p:
|
||||
:/^X/,$w! test.out
|
||||
:qa!
|
||||
ENDTEST
|
||||
|
||||
Xabcdefghijkemnopqretuvwxyz
|
||||
Yabcdefghijkemnopqretuvwxyz
|
||||
Zabcdefghijkemnokqretkvwxyz
|
3
src/nvim/testdir/test_charsearch.ok
Normal file
3
src/nvim/testdir/test_charsearch.ok
Normal file
@ -0,0 +1,3 @@
|
||||
XabcdeXfghijkeXmnopqreXtuvwxyz
|
||||
YabcdeYfghiYjkeYmnopqreYtuvwxyz
|
||||
ZabcdeZfghijkZemnokZqretkZvwxyz
|
@ -71,6 +71,42 @@ static char *features[] = {
|
||||
|
||||
// clang-format off
|
||||
static int included_patches[] = {
|
||||
826,
|
||||
//825,
|
||||
//824 NA
|
||||
//823,
|
||||
//822,
|
||||
//821,
|
||||
//820,
|
||||
//819,
|
||||
//818,
|
||||
//817,
|
||||
//816,
|
||||
//815,
|
||||
//814,
|
||||
813,
|
||||
//812,
|
||||
//811,
|
||||
//810,
|
||||
//809,
|
||||
//808,
|
||||
//807,
|
||||
//806,
|
||||
//805,
|
||||
//804,
|
||||
//803,
|
||||
//802,
|
||||
//801,
|
||||
//800,
|
||||
//799,
|
||||
//798,
|
||||
//797,
|
||||
//796,
|
||||
//795,
|
||||
//794,
|
||||
//793,
|
||||
//792,
|
||||
//791,
|
||||
//790,
|
||||
//789,
|
||||
//788,
|
||||
|
Loading…
Reference in New Issue
Block a user