mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge #8866 from janlazo/vim-8.0.0878
This commit is contained in:
commit
0839c44257
@ -163,12 +163,14 @@ CTRL-R CTRL-F *c_CTRL-R_CTRL-F* *c_<C-R>_<C-F>*
|
||||
CTRL-R CTRL-P *c_CTRL-R_CTRL-P* *c_<C-R>_<C-P>*
|
||||
CTRL-R CTRL-W *c_CTRL-R_CTRL-W* *c_<C-R>_<C-W>*
|
||||
CTRL-R CTRL-A *c_CTRL-R_CTRL-A* *c_<C-R>_<C-A>*
|
||||
CTRL-R CTRL-L *c_CTRL-R_CTRL-L* *c_<C-R>_<C-L>*
|
||||
Insert the object under the cursor:
|
||||
CTRL-F the Filename under the cursor
|
||||
CTRL-P the Filename under the cursor, expanded with
|
||||
'path' as in |gf|
|
||||
CTRL-W the Word under the cursor
|
||||
CTRL-A the WORD under the cursor; see |WORD|
|
||||
CTRL-L the line under the cursor
|
||||
|
||||
When 'incsearch' is set the cursor position at the end of the
|
||||
currently displayed match is used. With CTRL-W the part of
|
||||
@ -176,8 +178,8 @@ CTRL-R CTRL-A *c_CTRL-R_CTRL-A* *c_<C-R>_<C-A>*
|
||||
|
||||
*c_CTRL-R_CTRL-R* *c_<C-R>_<C-R>*
|
||||
*c_CTRL-R_CTRL-O* *c_<C-R>_<C-O>*
|
||||
CTRL-R CTRL-R {0-9a-z"%#:-=. CTRL-F CTRL-P CTRL-W CTRL-A}
|
||||
CTRL-R CTRL-O {0-9a-z"%#:-=. CTRL-F CTRL-P CTRL-W CTRL-A}
|
||||
CTRL-R CTRL-R {0-9a-z"%#:-=. CTRL-F CTRL-P CTRL-W CTRL-A CTRL-L}
|
||||
CTRL-R CTRL-O {0-9a-z"%#:-=. CTRL-F CTRL-P CTRL-W CTRL-A CTRL-L}
|
||||
Insert register or object under the cursor. Works like
|
||||
|c_CTRL-R| but inserts the text literally. For example, if
|
||||
register a contains "xy^Hz" (where ^H is a backspace),
|
||||
@ -786,6 +788,11 @@ Also see |`=|.
|
||||
Note: these are typed literally, they are not special keys!
|
||||
<cword> is replaced with the word under the cursor (like |star|)
|
||||
<cWORD> is replaced with the WORD under the cursor (see |WORD|)
|
||||
<cexpr> is replaced with the word under the cursor, including more
|
||||
to form a C expression. E.g., when the cursor is on "arg"
|
||||
of "ptr->arg" then the result is "ptr->arg"; when the
|
||||
cursor is on "]" of "list[idx]" then the result is
|
||||
"list[idx]". This is used for |v:beval_text|.
|
||||
<cfile> is replaced with the path name under the cursor (like what
|
||||
|gf| uses)
|
||||
<afile> When executing autocommands, is replaced with the file name
|
||||
|
@ -4079,6 +4079,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
|
||||
specifies what for. The following completion types are
|
||||
supported:
|
||||
|
||||
arglist file names in argument list
|
||||
augroup autocmd groups
|
||||
buffer buffer names
|
||||
behave :behave suboptions
|
||||
@ -4099,6 +4100,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
|
||||
highlight highlight groups
|
||||
history :history suboptions
|
||||
locale locale names (as output of locale -a)
|
||||
mapclear buffer argument
|
||||
mapping mapping name
|
||||
menu menus
|
||||
messages |:messages| suboptions
|
||||
|
@ -1208,6 +1208,7 @@ By default, the arguments of user defined commands do not undergo completion.
|
||||
However, by specifying one or the other of the following attributes, argument
|
||||
completion can be enabled:
|
||||
|
||||
-complete=arglist file names in argument list
|
||||
-complete=augroup autocmd groups
|
||||
-complete=buffer buffer names
|
||||
-complete=behave :behave suboptions
|
||||
@ -1227,6 +1228,7 @@ completion can be enabled:
|
||||
-complete=highlight highlight groups
|
||||
-complete=history :history suboptions
|
||||
-complete=locale locale names (as output of locale -a)
|
||||
-complete=mapclear buffer argument
|
||||
-complete=mapping mapping name
|
||||
-complete=menu menus
|
||||
-complete=messages |:messages| suboptions
|
||||
|
@ -2659,9 +2659,8 @@ buf_T *setaltfname(char_u *ffname, char_u *sfname, linenr_T lnum)
|
||||
* Get alternate file name for current window.
|
||||
* Return NULL if there isn't any, and give error message if requested.
|
||||
*/
|
||||
char_u *
|
||||
getaltfname (
|
||||
int errmsg /* give error message */
|
||||
char_u * getaltfname(
|
||||
bool errmsg // give error message
|
||||
)
|
||||
{
|
||||
char_u *fname;
|
||||
|
@ -2254,6 +2254,15 @@ static int alist_add_list(int count, char_u **files, int after)
|
||||
}
|
||||
}
|
||||
|
||||
// Function given to ExpandGeneric() to obtain the possible arguments of the
|
||||
// argedit and argdelete commands.
|
||||
char_u *get_arglist_name(expand_T *xp FUNC_ATTR_UNUSED, int idx)
|
||||
{
|
||||
if (idx >= ARGCOUNT) {
|
||||
return NULL;
|
||||
}
|
||||
return alist_name(&ARGLIST[idx]);
|
||||
}
|
||||
|
||||
/// ":compiler[!] {name}"
|
||||
void ex_compiler(exarg_T *eap)
|
||||
|
@ -2665,8 +2665,8 @@ const char * set_one_cmd_context(
|
||||
size_t len = 0;
|
||||
exarg_T ea;
|
||||
int context = EXPAND_NOTHING;
|
||||
int forceit = false;
|
||||
int usefilter = false; // Filter instead of file name.
|
||||
bool forceit = false;
|
||||
bool usefilter = false; // Filter instead of file name.
|
||||
|
||||
ExpandInit(xp);
|
||||
xp->xp_pattern = (char_u *)buff;
|
||||
@ -2786,9 +2786,9 @@ const char * set_one_cmd_context(
|
||||
|
||||
xp->xp_context = EXPAND_NOTHING; /* Default now that we're past command */
|
||||
|
||||
if (*p == '!') { /* forced commands */
|
||||
forceit = TRUE;
|
||||
++p;
|
||||
if (*p == '!') { // forced commands
|
||||
forceit = true;
|
||||
p++;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2813,10 +2813,10 @@ const char * set_one_cmd_context(
|
||||
}
|
||||
|
||||
if (ea.cmdidx == CMD_read) {
|
||||
usefilter = forceit; /* :r! filter if forced */
|
||||
if (*arg == '!') { /* :r !filter */
|
||||
++arg;
|
||||
usefilter = TRUE;
|
||||
usefilter = forceit; // :r! filter if forced
|
||||
if (*arg == '!') { // :r !filter
|
||||
arg++;
|
||||
usefilter = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2978,7 +2978,7 @@ const char * set_one_cmd_context(
|
||||
// A full match ~user<Tab> will be replaced by user's home
|
||||
// directory i.e. something like ~user<Tab> -> /home/user/
|
||||
if (*p == NUL && p > (const char *)xp->xp_pattern + 1
|
||||
&& match_user(xp->xp_pattern + 1) == 1) {
|
||||
&& match_user(xp->xp_pattern + 1) >= 1) {
|
||||
xp->xp_context = EXPAND_USER;
|
||||
++xp->xp_pattern;
|
||||
}
|
||||
@ -3350,6 +3350,19 @@ const char * set_one_cmd_context(
|
||||
case CMD_xunmap:
|
||||
return (const char *)set_context_in_map_cmd(
|
||||
xp, (char_u *)cmd, (char_u *)arg, forceit, false, true, ea.cmdidx);
|
||||
case CMD_mapclear:
|
||||
case CMD_nmapclear:
|
||||
case CMD_vmapclear:
|
||||
case CMD_omapclear:
|
||||
case CMD_imapclear:
|
||||
case CMD_cmapclear:
|
||||
case CMD_lmapclear:
|
||||
case CMD_smapclear:
|
||||
case CMD_xmapclear:
|
||||
xp->xp_context = EXPAND_MAPCLEAR;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_abbreviate: case CMD_noreabbrev:
|
||||
case CMD_cabbrev: case CMD_cnoreabbrev:
|
||||
case CMD_iabbrev: case CMD_inoreabbrev:
|
||||
@ -3441,6 +3454,13 @@ const char * set_one_cmd_context(
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_argdelete:
|
||||
while ((xp->xp_pattern = vim_strchr((const char_u *)arg, ' ')) != NULL) {
|
||||
arg = (const char *)(xp->xp_pattern + 1);
|
||||
}
|
||||
xp->xp_context = EXPAND_ARGLIST;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -4846,6 +4866,7 @@ static struct {
|
||||
*/
|
||||
static const char *command_complete[] =
|
||||
{
|
||||
[EXPAND_ARGLIST] = "arglist",
|
||||
[EXPAND_AUGROUP] = "augroup",
|
||||
[EXPAND_BEHAVE] = "behave",
|
||||
[EXPAND_BUFFERS] = "buffer",
|
||||
@ -4870,6 +4891,7 @@ static const char *command_complete[] =
|
||||
#ifdef HAVE_WORKING_LIBINTL
|
||||
[EXPAND_LOCALES] = "locale",
|
||||
#endif
|
||||
[EXPAND_MAPCLEAR] = "mapclear",
|
||||
[EXPAND_MAPPINGS] = "mapping",
|
||||
[EXPAND_MENUS] = "menu",
|
||||
[EXPAND_MESSAGES] = "messages",
|
||||
@ -8370,23 +8392,25 @@ ssize_t find_cmdline_var(const char_u *src, size_t *usedlen)
|
||||
"%",
|
||||
#define SPEC_PERC 0
|
||||
"#",
|
||||
#define SPEC_HASH 1
|
||||
"<cword>", /* cursor word */
|
||||
#define SPEC_CWORD 2
|
||||
"<cWORD>", /* cursor WORD */
|
||||
#define SPEC_CCWORD 3
|
||||
"<cfile>", /* cursor path name */
|
||||
#define SPEC_CFILE 4
|
||||
"<sfile>", /* ":so" file name */
|
||||
#define SPEC_SFILE 5
|
||||
"<slnum>", /* ":so" file line number */
|
||||
#define SPEC_SLNUM 6
|
||||
"<afile>", /* autocommand file name */
|
||||
# define SPEC_AFILE 7
|
||||
"<abuf>", /* autocommand buffer number */
|
||||
# define SPEC_ABUF 8
|
||||
"<amatch>", /* autocommand match name */
|
||||
# define SPEC_AMATCH 9
|
||||
#define SPEC_HASH (SPEC_PERC + 1)
|
||||
"<cword>", // cursor word
|
||||
#define SPEC_CWORD (SPEC_HASH + 1)
|
||||
"<cWORD>", // cursor WORD
|
||||
#define SPEC_CCWORD (SPEC_CWORD + 1)
|
||||
"<cexpr>", // expr under cursor
|
||||
#define SPEC_CEXPR (SPEC_CCWORD + 1)
|
||||
"<cfile>", // cursor path name
|
||||
#define SPEC_CFILE (SPEC_CEXPR + 1)
|
||||
"<sfile>", // ":so" file name
|
||||
#define SPEC_SFILE (SPEC_CFILE + 1)
|
||||
"<slnum>", // ":so" file line number
|
||||
#define SPEC_SLNUM (SPEC_SFILE + 1)
|
||||
"<afile>", // autocommand file name
|
||||
#define SPEC_AFILE (SPEC_SLNUM + 1)
|
||||
"<abuf>", // autocommand buffer number
|
||||
#define SPEC_ABUF (SPEC_AFILE + 1)
|
||||
"<amatch>", // autocommand match name
|
||||
#define SPEC_AMATCH (SPEC_ABUF + 1)
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(spec_str); ++i) {
|
||||
@ -8467,10 +8491,16 @@ eval_vars (
|
||||
/*
|
||||
* word or WORD under cursor
|
||||
*/
|
||||
if (spec_idx == SPEC_CWORD || spec_idx == SPEC_CCWORD) {
|
||||
resultlen = find_ident_under_cursor(&result, (spec_idx == SPEC_CWORD
|
||||
? (FIND_IDENT|FIND_STRING)
|
||||
: FIND_STRING));
|
||||
if (spec_idx == SPEC_CWORD
|
||||
|| spec_idx == SPEC_CCWORD
|
||||
|| spec_idx == SPEC_CEXPR) {
|
||||
resultlen = find_ident_under_cursor(
|
||||
&result,
|
||||
spec_idx == SPEC_CWORD
|
||||
? (FIND_IDENT | FIND_STRING)
|
||||
: (spec_idx == SPEC_CEXPR
|
||||
? (FIND_IDENT | FIND_STRING | FIND_EVAL)
|
||||
: FIND_STRING));
|
||||
if (resultlen == 0) {
|
||||
*errormsg = (char_u *)"";
|
||||
return NULL;
|
||||
@ -8507,9 +8537,13 @@ eval_vars (
|
||||
if (*s == '<') /* "#<99" uses v:oldfiles */
|
||||
++s;
|
||||
i = getdigits_int(&s);
|
||||
*usedlen = (size_t)(s - src); /* length of what we expand */
|
||||
if (s == src + 2 && src[1] == '-') {
|
||||
// just a minus sign, don't skip over it
|
||||
s--;
|
||||
}
|
||||
*usedlen = (size_t)(s - src); // length of what we expand
|
||||
|
||||
if (src[1] == '<') {
|
||||
if (src[1] == '<' && i != 0) {
|
||||
if (*usedlen < 2) {
|
||||
/* Should we give an error message for #<text? */
|
||||
*usedlen = 1;
|
||||
@ -8522,6 +8556,9 @@ eval_vars (
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (i == 0 && src[1] == '<' && *usedlen > 1) {
|
||||
*usedlen = 1;
|
||||
}
|
||||
buf = buflist_findnr(i);
|
||||
if (buf == NULL) {
|
||||
*errormsg = (char_u *)_(
|
||||
@ -9655,6 +9692,14 @@ char_u *get_messages_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char_u *get_mapclear_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
|
||||
{
|
||||
if (idx == 0) {
|
||||
return (char_u *)"<buffer>";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static TriState filetype_detect = kNone;
|
||||
static TriState filetype_plugin = kNone;
|
||||
static TriState filetype_indent = kNone;
|
||||
|
@ -3290,17 +3290,18 @@ void restore_cmdline_alloc(char_u *p)
|
||||
/// @returns FAIL for failure, OK otherwise
|
||||
static bool cmdline_paste(int regname, bool literally, bool remcr)
|
||||
{
|
||||
long i;
|
||||
char_u *arg;
|
||||
char_u *p;
|
||||
int allocated;
|
||||
bool allocated;
|
||||
struct cmdline_info save_ccline;
|
||||
|
||||
/* check for valid regname; also accept special characters for CTRL-R in
|
||||
* the command line */
|
||||
if (regname != Ctrl_F && regname != Ctrl_P && regname != Ctrl_W
|
||||
&& regname != Ctrl_A && !valid_yank_reg(regname, false))
|
||||
&& regname != Ctrl_A && regname != Ctrl_L
|
||||
&& !valid_yank_reg(regname, false)) {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
/* A register containing CTRL-R can cause an endless loop. Allow using
|
||||
* CTRL-C to break the loop. */
|
||||
@ -3312,9 +3313,9 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
|
||||
/* Need to save and restore ccline. And set "textlock" to avoid nasty
|
||||
* things like going to another buffer when evaluating an expression. */
|
||||
save_cmdline(&save_ccline);
|
||||
++textlock;
|
||||
i = get_spec_reg(regname, &arg, &allocated, TRUE);
|
||||
--textlock;
|
||||
textlock++;
|
||||
const bool i = get_spec_reg(regname, &arg, &allocated, true);
|
||||
textlock--;
|
||||
restore_cmdline(&save_ccline);
|
||||
|
||||
if (i) {
|
||||
@ -4760,6 +4761,7 @@ ExpandFromContext (
|
||||
} tab[] = {
|
||||
{ EXPAND_COMMANDS, get_command_name, false, true },
|
||||
{ EXPAND_BEHAVE, get_behave_arg, true, true },
|
||||
{ EXPAND_MAPCLEAR, get_mapclear_arg, true, true },
|
||||
{ EXPAND_MESSAGES, get_messages_arg, true, true },
|
||||
{ EXPAND_HISTORY, get_history_arg, true, true },
|
||||
{ EXPAND_USER_COMMANDS, get_user_commands, false, true },
|
||||
@ -4787,6 +4789,7 @@ ExpandFromContext (
|
||||
#endif
|
||||
{ EXPAND_ENV_VARS, get_env_name, true, true },
|
||||
{ EXPAND_USER, get_users, true, false },
|
||||
{ EXPAND_ARGLIST, get_arglist_name, true, false },
|
||||
};
|
||||
int i;
|
||||
|
||||
|
@ -2990,6 +2990,43 @@ void reset_VIsual(void)
|
||||
}
|
||||
}
|
||||
|
||||
// Check for a balloon-eval special item to include when searching for an
|
||||
// identifier. When "dir" is BACKWARD "ptr[-1]" must be valid!
|
||||
// Returns true if the character at "*ptr" should be included.
|
||||
// "dir" is FORWARD or BACKWARD, the direction of searching.
|
||||
// "*colp" is in/decremented if "ptr[-dir]" should also be included.
|
||||
// "bnp" points to a counter for square brackets.
|
||||
static bool find_is_eval_item(
|
||||
const char_u *const ptr,
|
||||
int *const colp,
|
||||
int *const bnp,
|
||||
const int dir)
|
||||
{
|
||||
// Accept everything inside [].
|
||||
if ((*ptr == ']' && dir == BACKWARD) || (*ptr == '[' && dir == FORWARD)) {
|
||||
*bnp += 1;
|
||||
}
|
||||
if (*bnp > 0) {
|
||||
if ((*ptr == '[' && dir == BACKWARD) || (*ptr == ']' && dir == FORWARD)) {
|
||||
*bnp -= 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// skip over "s.var"
|
||||
if (*ptr == '.') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// two-character item: s->var
|
||||
if (ptr[dir == BACKWARD ? 0 : 1] == '>'
|
||||
&& ptr[dir == BACKWARD ? -1 : 0] == '-') {
|
||||
*colp += dir;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the identifier under or to the right of the cursor.
|
||||
* "find_type" can have one of three values:
|
||||
@ -3030,6 +3067,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol,
|
||||
int this_class = 0;
|
||||
int prev_class;
|
||||
int prevcol;
|
||||
int bn = 0; // bracket nesting
|
||||
|
||||
/*
|
||||
* if i == 0: try to find an identifier
|
||||
@ -3041,71 +3079,62 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol,
|
||||
* 1. skip to start of identifier/string
|
||||
*/
|
||||
col = startcol;
|
||||
if (has_mbyte) {
|
||||
while (ptr[col] != NUL) {
|
||||
this_class = mb_get_class(ptr + col);
|
||||
if (this_class != 0 && (i == 1 || this_class != 1))
|
||||
break;
|
||||
col += (*mb_ptr2len)(ptr + col);
|
||||
while (ptr[col] != NUL) {
|
||||
// Stop at a ']' to evaluate "a[x]".
|
||||
if ((find_type & FIND_EVAL) && ptr[col] == ']') {
|
||||
break;
|
||||
}
|
||||
} else
|
||||
while (ptr[col] != NUL
|
||||
&& (i == 0 ? !vim_iswordc(ptr[col]) : ascii_iswhite(ptr[col]))
|
||||
)
|
||||
++col;
|
||||
this_class = mb_get_class(ptr + col);
|
||||
if (this_class != 0 && (i == 1 || this_class != 1)) {
|
||||
break;
|
||||
}
|
||||
col += utfc_ptr2len(ptr + col);
|
||||
}
|
||||
|
||||
// When starting on a ']' count it, so that we include the '['.
|
||||
bn = ptr[col] == ']';
|
||||
|
||||
/*
|
||||
* 2. Back up to start of identifier/string.
|
||||
*/
|
||||
if (has_mbyte) {
|
||||
/* Remember class of character under cursor. */
|
||||
this_class = mb_get_class(ptr + col);
|
||||
while (col > 0 && this_class != 0) {
|
||||
prevcol = col - 1 - (*mb_head_off)(ptr, ptr + col - 1);
|
||||
prev_class = mb_get_class(ptr + prevcol);
|
||||
if (this_class != prev_class
|
||||
&& (i == 0
|
||||
|| prev_class == 0
|
||||
|| (find_type & FIND_IDENT))
|
||||
)
|
||||
break;
|
||||
col = prevcol;
|
||||
}
|
||||
|
||||
/* If we don't want just any old string, or we've found an
|
||||
* identifier, stop searching. */
|
||||
if (this_class > 2)
|
||||
this_class = 2;
|
||||
if (!(find_type & FIND_STRING) || this_class == 2)
|
||||
break;
|
||||
// Remember class of character under cursor.
|
||||
if ((find_type & FIND_EVAL) && ptr[col] == ']') {
|
||||
this_class = mb_get_class((char_u *)"a");
|
||||
} else {
|
||||
while (col > 0
|
||||
&& ((i == 0
|
||||
? vim_iswordc(ptr[col - 1])
|
||||
: (!ascii_iswhite(ptr[col - 1])
|
||||
&& (!(find_type & FIND_IDENT)
|
||||
|| !vim_iswordc(ptr[col - 1]))))
|
||||
))
|
||||
--col;
|
||||
|
||||
/* If we don't want just any old string, or we've found an
|
||||
* identifier, stop searching. */
|
||||
if (!(find_type & FIND_STRING) || vim_iswordc(ptr[col]))
|
||||
this_class = mb_get_class(ptr + col);
|
||||
}
|
||||
while (col > 0 && this_class != 0) {
|
||||
prevcol = col - 1 - utf_head_off(ptr, ptr + col - 1);
|
||||
prev_class = mb_get_class(ptr + prevcol);
|
||||
if (this_class != prev_class
|
||||
&& (i == 0
|
||||
|| prev_class == 0
|
||||
|| (find_type & FIND_IDENT))
|
||||
&& (!(find_type & FIND_EVAL)
|
||||
|| prevcol == 0
|
||||
|| !find_is_eval_item(ptr + prevcol, &prevcol, &bn, BACKWARD))) {
|
||||
break;
|
||||
}
|
||||
col = prevcol;
|
||||
}
|
||||
|
||||
// If we don't want just any old string, or we've found an
|
||||
// identifier, stop searching.
|
||||
if (this_class > 2) {
|
||||
this_class = 2;
|
||||
}
|
||||
if (!(find_type & FIND_STRING) || this_class == 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr[col] == NUL || (i == 0 && (
|
||||
has_mbyte ? this_class != 2 :
|
||||
!vim_iswordc(ptr[col])))) {
|
||||
/*
|
||||
* didn't find an identifier or string
|
||||
*/
|
||||
if (find_type & FIND_STRING)
|
||||
if (ptr[col] == NUL || (i == 0 && this_class != 2)) {
|
||||
// didn't find an identifier or string
|
||||
if (find_type & FIND_STRING) {
|
||||
EMSG(_("E348: No string under cursor"));
|
||||
else
|
||||
} else {
|
||||
EMSG(_(e_noident));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ptr += col;
|
||||
@ -3114,21 +3143,20 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol,
|
||||
/*
|
||||
* 3. Find the end if the identifier/string.
|
||||
*/
|
||||
bn = 0;
|
||||
startcol -= col;
|
||||
col = 0;
|
||||
if (has_mbyte) {
|
||||
/* Search for point of changing multibyte character class. */
|
||||
this_class = mb_get_class(ptr);
|
||||
while (ptr[col] != NUL
|
||||
&& ((i == 0 ? mb_get_class(ptr + col) == this_class
|
||||
: mb_get_class(ptr + col) != 0)
|
||||
))
|
||||
col += (*mb_ptr2len)(ptr + col);
|
||||
} else
|
||||
while ((i == 0 ? vim_iswordc(ptr[col])
|
||||
: (ptr[col] != NUL && !ascii_iswhite(ptr[col])))
|
||||
) {
|
||||
++col;
|
||||
}
|
||||
// Search for point of changing multibyte character class.
|
||||
this_class = mb_get_class(ptr);
|
||||
while (ptr[col] != NUL
|
||||
&& ((i == 0
|
||||
? mb_get_class(ptr + col) == this_class
|
||||
: mb_get_class(ptr + col) != 0)
|
||||
|| ((find_type & FIND_EVAL)
|
||||
&& col <= (int)startcol
|
||||
&& find_is_eval_item(ptr + col, &col, &bn, FORWARD)))) {
|
||||
col += utfc_ptr2len(ptr + col);
|
||||
}
|
||||
|
||||
assert(col >= 0);
|
||||
return (size_t)col;
|
||||
|
@ -1110,7 +1110,7 @@ int insert_reg(
|
||||
)
|
||||
{
|
||||
int retval = OK;
|
||||
int allocated;
|
||||
bool allocated;
|
||||
|
||||
/*
|
||||
* It is possible to get into an endless loop by having CTRL-R a in
|
||||
@ -1187,82 +1187,92 @@ static void stuffescaped(const char *arg, int literally)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If "regname" is a special register, return TRUE and store a pointer to its
|
||||
* value in "argp".
|
||||
*/
|
||||
int get_spec_reg(
|
||||
// If "regname" is a special register, return true and store a pointer to its
|
||||
// value in "argp".
|
||||
bool get_spec_reg(
|
||||
int regname,
|
||||
char_u **argp,
|
||||
int *allocated, /* return: TRUE when value was allocated */
|
||||
int errmsg /* give error message when failing */
|
||||
bool *allocated, // return: true when value was allocated
|
||||
bool errmsg // give error message when failing
|
||||
)
|
||||
{
|
||||
size_t cnt;
|
||||
|
||||
*argp = NULL;
|
||||
*allocated = FALSE;
|
||||
*allocated = false;
|
||||
switch (regname) {
|
||||
case '%': /* file name */
|
||||
if (errmsg)
|
||||
check_fname(); /* will give emsg if not set */
|
||||
*argp = curbuf->b_fname;
|
||||
return TRUE;
|
||||
return true;
|
||||
|
||||
case '#': /* alternate file name */
|
||||
*argp = getaltfname(errmsg); /* may give emsg if not set */
|
||||
return TRUE;
|
||||
case '#': // alternate file name
|
||||
*argp = getaltfname(errmsg); // may give emsg if not set
|
||||
return true;
|
||||
|
||||
case '=': /* result of expression */
|
||||
*argp = get_expr_line();
|
||||
*allocated = TRUE;
|
||||
return TRUE;
|
||||
*allocated = true;
|
||||
return true;
|
||||
|
||||
case ':': /* last command line */
|
||||
if (last_cmdline == NULL && errmsg)
|
||||
EMSG(_(e_nolastcmd));
|
||||
*argp = last_cmdline;
|
||||
return TRUE;
|
||||
return true;
|
||||
|
||||
case '/': /* last search-pattern */
|
||||
if (last_search_pat() == NULL && errmsg)
|
||||
EMSG(_(e_noprevre));
|
||||
*argp = last_search_pat();
|
||||
return TRUE;
|
||||
return true;
|
||||
|
||||
case '.': /* last inserted text */
|
||||
*argp = get_last_insert_save();
|
||||
*allocated = TRUE;
|
||||
if (*argp == NULL && errmsg)
|
||||
*allocated = true;
|
||||
if (*argp == NULL && errmsg) {
|
||||
EMSG(_(e_noinstext));
|
||||
return TRUE;
|
||||
}
|
||||
return true;
|
||||
|
||||
case Ctrl_F: /* Filename under cursor */
|
||||
case Ctrl_P: /* Path under cursor, expand via "path" */
|
||||
if (!errmsg)
|
||||
return FALSE;
|
||||
*argp = file_name_at_cursor(FNAME_MESS | FNAME_HYP
|
||||
| (regname == Ctrl_P ? FNAME_EXP : 0), 1L, NULL);
|
||||
*allocated = TRUE;
|
||||
return TRUE;
|
||||
case Ctrl_F: // Filename under cursor
|
||||
case Ctrl_P: // Path under cursor, expand via "path"
|
||||
if (!errmsg) {
|
||||
return false;
|
||||
}
|
||||
*argp = file_name_at_cursor(
|
||||
FNAME_MESS | FNAME_HYP | (regname == Ctrl_P ? FNAME_EXP : 0),
|
||||
1L, NULL);
|
||||
*allocated = true;
|
||||
return true;
|
||||
|
||||
case Ctrl_W: /* word under cursor */
|
||||
case Ctrl_A: /* WORD (mnemonic All) under cursor */
|
||||
if (!errmsg)
|
||||
return FALSE;
|
||||
case Ctrl_W: // word under cursor
|
||||
case Ctrl_A: // WORD (mnemonic All) under cursor
|
||||
if (!errmsg) {
|
||||
return false;
|
||||
}
|
||||
cnt = find_ident_under_cursor(argp, (regname == Ctrl_W
|
||||
? (FIND_IDENT|FIND_STRING)
|
||||
: FIND_STRING));
|
||||
*argp = cnt ? vim_strnsave(*argp, cnt) : NULL;
|
||||
*allocated = TRUE;
|
||||
return TRUE;
|
||||
*allocated = true;
|
||||
return true;
|
||||
|
||||
case Ctrl_L: // Line under cursor
|
||||
if (!errmsg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*argp = ml_get_buf(curwin->w_buffer, curwin->w_cursor.lnum, false);
|
||||
return true;
|
||||
|
||||
case '_': /* black hole: always empty */
|
||||
*argp = (char_u *)"";
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Paste a yank register into the command line.
|
||||
@ -2652,7 +2662,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
|
||||
int lendiff = 0;
|
||||
pos_T old_pos;
|
||||
char_u *insert_string = NULL;
|
||||
int allocated = FALSE;
|
||||
bool allocated = false;
|
||||
long cnt;
|
||||
|
||||
if (flags & PUT_FIXINDENT)
|
||||
@ -2748,9 +2758,10 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
|
||||
* For special registers '%' (file name), '#' (alternate file name) and
|
||||
* ':' (last command line), etc. we have to create a fake yank register.
|
||||
*/
|
||||
if (get_spec_reg(regname, &insert_string, &allocated, TRUE)) {
|
||||
if (insert_string == NULL)
|
||||
if (get_spec_reg(regname, &insert_string, &allocated, true)) {
|
||||
if (insert_string == NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!curbuf->terminal) {
|
||||
@ -4907,10 +4918,11 @@ void *get_reg_contents(int regname, int flags)
|
||||
return NULL;
|
||||
|
||||
char_u *retval;
|
||||
int allocated;
|
||||
if (get_spec_reg(regname, &retval, &allocated, FALSE)) {
|
||||
if (retval == NULL)
|
||||
bool allocated;
|
||||
if (get_spec_reg(regname, &retval, &allocated, false)) {
|
||||
if (retval == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (allocated) {
|
||||
return get_reg_wrap_one_line(retval, flags);
|
||||
}
|
||||
|
@ -137,6 +137,11 @@ func Test_getcompletion()
|
||||
let l = getcompletion('v:notexists', 'var')
|
||||
call assert_equal([], l)
|
||||
|
||||
args a.c b.c
|
||||
let l = getcompletion('', 'arglist')
|
||||
call assert_equal(['a.c', 'b.c'], l)
|
||||
%argdelete
|
||||
|
||||
let l = getcompletion('', 'augroup')
|
||||
call assert_true(index(l, 'END') >= 0)
|
||||
let l = getcompletion('blahblah', 'augroup')
|
||||
@ -222,6 +227,11 @@ func Test_getcompletion()
|
||||
let l = getcompletion('not', 'messages')
|
||||
call assert_equal([], l)
|
||||
|
||||
let l = getcompletion('', 'mapclear')
|
||||
call assert_true(index(l, '<buffer>') >= 0)
|
||||
let l = getcompletion('not', 'mapclear')
|
||||
call assert_equal([], l)
|
||||
|
||||
if has('cscope')
|
||||
let l = getcompletion('', 'cscope')
|
||||
let cmds = ['add', 'find', 'help', 'kill', 'reset', 'show']
|
||||
@ -311,6 +321,9 @@ func Test_paste_in_cmdline()
|
||||
call feedkeys("ft:aaa \<C-R>\<C-F> bbb\<C-B>\"\<CR>", 'tx')
|
||||
call assert_equal('"aaa /tmp/some bbb', @:)
|
||||
|
||||
call feedkeys(":aaa \<C-R>\<C-L> bbb\<C-B>\"\<CR>", 'tx')
|
||||
call assert_equal('"aaa '.getline(1).' bbb', @:)
|
||||
|
||||
set incsearch
|
||||
call feedkeys("fy:aaa veryl\<C-R>\<C-W> bbb\<C-B>\"\<CR>", 'tx')
|
||||
call assert_equal('"aaa verylongword bbb', @:)
|
||||
@ -375,6 +388,27 @@ func Test_cmdline_complete_user_cmd()
|
||||
delcommand Foo
|
||||
endfunc
|
||||
|
||||
func Test_cmdline_write_alternatefile()
|
||||
new
|
||||
call setline('.', ['one', 'two'])
|
||||
f foo.txt
|
||||
new
|
||||
f #-A
|
||||
call assert_equal('foo.txt-A', expand('%'))
|
||||
f #<-B.txt
|
||||
call assert_equal('foo-B.txt', expand('%'))
|
||||
f %<
|
||||
call assert_equal('foo-B', expand('%'))
|
||||
new
|
||||
call assert_fails('f #<', 'E95')
|
||||
bw!
|
||||
f foo-B.txt
|
||||
f %<-A
|
||||
call assert_equal('foo-B-A', expand('%'))
|
||||
bw!
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
" using a leading backslash here
|
||||
set cpo+=C
|
||||
|
||||
@ -430,6 +464,22 @@ func Test_getcmdtype()
|
||||
cunmap <F6>
|
||||
endfunc
|
||||
|
||||
func Test_getcmdwintype()
|
||||
call feedkeys("q/:let a = getcmdwintype()\<CR>:q\<CR>", 'x!')
|
||||
call assert_equal('/', a)
|
||||
|
||||
call feedkeys("q?:let a = getcmdwintype()\<CR>:q\<CR>", 'x!')
|
||||
call assert_equal('?', a)
|
||||
|
||||
call feedkeys("q::let a = getcmdwintype()\<CR>:q\<CR>", 'x!')
|
||||
call assert_equal(':', a)
|
||||
|
||||
call feedkeys(":\<C-F>:let a = getcmdwintype()\<CR>:q\<CR>", 'x!')
|
||||
call assert_equal(':', a)
|
||||
|
||||
call assert_equal('', getcmdwintype())
|
||||
endfunc
|
||||
|
||||
func Test_verbosefile()
|
||||
set verbosefile=Xlog
|
||||
echomsg 'foo'
|
||||
@ -440,4 +490,25 @@ func Test_verbosefile()
|
||||
call delete('Xlog')
|
||||
endfunc
|
||||
|
||||
func Test_setcmdpos()
|
||||
func InsertTextAtPos(text, pos)
|
||||
call assert_equal(0, setcmdpos(a:pos))
|
||||
return a:text
|
||||
endfunc
|
||||
|
||||
" setcmdpos() with position in the middle of the command line.
|
||||
call feedkeys(":\"12\<C-R>=InsertTextAtPos('a', 3)\<CR>b\<CR>", 'xt')
|
||||
call assert_equal('"1ab2', @:)
|
||||
|
||||
call feedkeys(":\"12\<C-R>\<C-R>=InsertTextAtPos('a', 3)\<CR>b\<CR>", 'xt')
|
||||
call assert_equal('"1b2a', @:)
|
||||
|
||||
" setcmdpos() with position beyond the end of the command line.
|
||||
call feedkeys(":\"12\<C-B>\<C-R>=InsertTextAtPos('a', 10)\<CR>b\<CR>", 'xt')
|
||||
call assert_equal('"12ab', @:)
|
||||
|
||||
" setcmdpos() returns 1 when not editing the command line.
|
||||
call assert_equal(1, setcmdpos(3))
|
||||
endfunc
|
||||
|
||||
set cpo&
|
||||
|
@ -392,10 +392,31 @@ func! Test_normal10_expand()
|
||||
call setline(1, ['1', 'ifooar,,cbar'])
|
||||
2
|
||||
norm! $
|
||||
let a=expand('<cword>')
|
||||
let b=expand('<cWORD>')
|
||||
call assert_equal('cbar', a)
|
||||
call assert_equal('ifooar,,cbar', b)
|
||||
call assert_equal('cbar', expand('<cword>'))
|
||||
call assert_equal('ifooar,,cbar', expand('<cWORD>'))
|
||||
|
||||
call setline(1, ['prx = list[idx];'])
|
||||
1
|
||||
let expected = ['', 'prx', 'prx', 'prx',
|
||||
\ 'list', 'list', 'list', 'list', 'list', 'list', 'list',
|
||||
\ 'idx', 'idx', 'idx', 'idx',
|
||||
\ 'list[idx]',
|
||||
\ '];',
|
||||
\ ]
|
||||
for i in range(1, 16)
|
||||
exe 'norm ' . i . '|'
|
||||
call assert_equal(expected[i], expand('<cexpr>'), 'i == ' . i)
|
||||
endfor
|
||||
|
||||
if executable('echo')
|
||||
" Test expand(`...`) i.e. backticks command expansion.
|
||||
" MS-Windows has a trailing space.
|
||||
call assert_match('^abcde *$', expand('`echo abcde`'))
|
||||
endif
|
||||
|
||||
" Test expand(`=...`) i.e. backticks expression expansion
|
||||
call assert_equal('5', expand('`=2+3`'))
|
||||
|
||||
" clean up
|
||||
bw!
|
||||
endfunc
|
||||
@ -1536,12 +1557,12 @@ fun! Test_normal29_brace()
|
||||
\ 'the ''{'' flag is in ''cpoptions'' then ''{'' in the first column is used as a',
|
||||
\ 'paragraph boundary |posix|.',
|
||||
\ '{',
|
||||
\ 'This is no paragaraph',
|
||||
\ 'This is no paragraph',
|
||||
\ 'unless the ''{'' is set',
|
||||
\ 'in ''cpoptions''',
|
||||
\ '}',
|
||||
\ '.IP',
|
||||
\ 'The nroff macros IP seperates a paragraph',
|
||||
\ 'The nroff macros IP separates a paragraph',
|
||||
\ 'That means, it must be a ''.''',
|
||||
\ 'followed by IP',
|
||||
\ '.LPIt does not matter, if afterwards some',
|
||||
@ -1556,7 +1577,7 @@ fun! Test_normal29_brace()
|
||||
1
|
||||
norm! 0d2}
|
||||
call assert_equal(['.IP',
|
||||
\ 'The nroff macros IP seperates a paragraph', 'That means, it must be a ''.''', 'followed by IP',
|
||||
\ 'The nroff macros IP separates a paragraph', 'That means, it must be a ''.''', 'followed by IP',
|
||||
\ '.LPIt does not matter, if afterwards some', 'more characters follow.', '.SHAlso section boundaries from the nroff',
|
||||
\ 'macros terminate a paragraph. That means', 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$'))
|
||||
norm! 0d}
|
||||
@ -1576,21 +1597,21 @@ fun! Test_normal29_brace()
|
||||
" set cpo+={
|
||||
" 1
|
||||
" norm! 0d2}
|
||||
" call assert_equal(['{', 'This is no paragaraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}',
|
||||
" \ '.IP', 'The nroff macros IP seperates a paragraph', 'That means, it must be a ''.''',
|
||||
" call assert_equal(['{', 'This is no paragraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}',
|
||||
" \ '.IP', 'The nroff macros IP separates a paragraph', 'That means, it must be a ''.''',
|
||||
" \ 'followed by IP', '.LPIt does not matter, if afterwards some', 'more characters follow.',
|
||||
" \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means',
|
||||
" \ 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$'))
|
||||
" $
|
||||
" norm! d}
|
||||
" call assert_equal(['{', 'This is no paragaraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}',
|
||||
" \ '.IP', 'The nroff macros IP seperates a paragraph', 'That means, it must be a ''.''',
|
||||
" call assert_equal(['{', 'This is no paragraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}',
|
||||
" \ '.IP', 'The nroff macros IP separates a paragraph', 'That means, it must be a ''.''',
|
||||
" \ 'followed by IP', '.LPIt does not matter, if afterwards some', 'more characters follow.',
|
||||
" \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means',
|
||||
" \ 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$'))
|
||||
" norm! gg}
|
||||
" norm! d5}
|
||||
" call assert_equal(['{', 'This is no paragaraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', ''], getline(1,'$'))
|
||||
" call assert_equal(['{', 'This is no paragraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', ''], getline(1,'$'))
|
||||
|
||||
" clean up
|
||||
set cpo-={
|
||||
|
@ -155,6 +155,8 @@ enum {
|
||||
EXPAND_USER_ADDR_TYPE,
|
||||
EXPAND_PACKADD,
|
||||
EXPAND_MESSAGES,
|
||||
EXPAND_MAPCLEAR,
|
||||
EXPAND_ARGLIST,
|
||||
EXPAND_CHECKHEALTH,
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user