📄 ex_docmd.c
字号:
return NULL;
if (*cmd == '"') /* ignore comment lines */
{
expand_context = EXPAND_NOTHING;
return NULL;
}
/*
* 3. parse a range specifier of the form: addr [,addr] [;addr] ..
*/
/*
* Backslashed delimiters after / or ? will be skipped, and commands will
* not be expanded between /'s and ?'s or after "'". -- webb
*/
while (*cmd != NUL && (vim_isspace(*cmd) || isdigit(*cmd) ||
vim_strchr((char_u *)".$%'/?-+,;", *cmd) != NULL))
{
if (*cmd == '\'')
{
if (*++cmd == NUL)
expand_context = EXPAND_NOTHING;
}
else if (*cmd == '/' || *cmd == '?')
{
delim = *cmd++;
while (*cmd != NUL && *cmd != delim)
if (*cmd++ == '\\' && *cmd != NUL)
++cmd;
if (*cmd == NUL)
expand_context = EXPAND_NOTHING;
}
if (*cmd != NUL)
++cmd;
}
/*
* 4. parse command
*/
cmd = skipwhite(cmd);
expand_pattern = cmd;
if (*cmd == NUL)
return NULL;
if (*cmd == '"')
{
expand_context = EXPAND_NOTHING;
return NULL;
}
if (*cmd == '|' || *cmd == '\n')
return cmd + 1; /* There's another command */
/*
* Isolate the command and search for it in the command table.
* Exceptions:
* - the 'k' command can directly be followed by any character.
* - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
*/
if (*cmd == 'k')
{
cmdidx = CMD_k;
p = cmd + 1;
}
else
{
p = cmd;
while (isalpha(*p) || *p == '*') /* Allow * wild card */
++p;
/* check for non-alpha command */
if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL)
++p;
i = (int)(p - cmd);
if (i == 0)
{
expand_context = EXPAND_UNSUCCESSFUL;
return NULL;
}
for (cmdidx = (CMDIDX)0; (int)cmdidx < (int)CMD_SIZE;
cmdidx = (CMDIDX)((int)cmdidx + 1))
if (STRNCMP(cmdnames[(int)cmdidx].cmd_name, cmd, (size_t)i) == 0)
break;
}
/*
* If the cursor is touching the command, and it ends in an alphabetic
* character, complete the command name.
*/
if (*p == NUL && isalpha(p[-1]))
return NULL;
if (cmdidx == CMD_SIZE)
{
if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL)
{
cmdidx = CMD_substitute;
p = cmd + 1;
}
else
{
#ifdef USER_COMMANDS
/* Look for a user defined command as a last resort */
UCMD *c = USER_CMD(0);
int j;
int found = FALSE;
for (j = 0; j < ucmds.ga_len; ++j, ++c)
{
if (STRNCMP(c->uc_name, cmd, (size_t)i) == 0)
{
if (found)
{
/* Ambiguous abbreviation */
expand_context = EXPAND_UNSUCCESSFUL;
return NULL;
}
found = TRUE;
cmdidx = CMD_USER;
argt = c->uc_argt;
compl = c->uc_compl;
/* Do not search for further abbreviations
* if this is an exact match
*/
if ((size_t)i == STRLEN(c->uc_name))
break;
}
}
if (!found)
#endif
{
/* Not still touching the command and it was an illegal one */
expand_context = EXPAND_UNSUCCESSFUL;
return NULL;
}
}
}
expand_context = EXPAND_NOTHING; /* Default now that we're past command */
if (*p == '!') /* forced commands */
{
forceit = TRUE;
++p;
}
/*
* 5. parse arguments
*/
#ifdef USER_COMMANDS
if (cmdidx != CMD_USER)
#endif
argt = cmdnames[(int)cmdidx].cmd_argt;
arg = skipwhite(p);
if (cmdidx == CMD_write || cmdidx == CMD_update)
{
if (*arg == '>') /* append */
{
if (*++arg == '>')
++arg;
arg = skipwhite(arg);
}
else if (*arg == '!' && cmdidx == CMD_write) /* :w !filter */
{
++arg;
usefilter = TRUE;
}
}
if (cmdidx == CMD_read)
{
usefilter = forceit; /* :r! filter if forced */
if (*arg == '!') /* :r !filter */
{
++arg;
usefilter = TRUE;
}
}
if (cmdidx == CMD_lshift || cmdidx == CMD_rshift)
{
while (*arg == *cmd) /* allow any number of '>' or '<' */
++arg;
arg = skipwhite(arg);
}
/* Does command allow "+command"? */
if ((argt & EDITCMD) && !usefilter && *arg == '+')
{
/* Check if we're in the +command */
p = arg + 1;
arg = skip_cmd_arg(arg);
/* Still touching the command after '+'? */
if (*arg == NUL)
return p;
/* Skip space(s) after +command to get to the real argument */
arg = skipwhite(arg);
}
/*
* Check for '|' to separate commands and '"' to start comments.
* Don't do this for ":read !cmd" and ":write !cmd".
*/
if ((argt & TRLBAR) && !usefilter)
{
p = arg;
while (*p)
{
if (*p == Ctrl('V'))
{
if (p[1] != NUL)
++p;
}
else if ( (*p == '"' && !(argt & NOTRLCOM))
|| *p == '|' || *p == '\n')
{
if (*(p - 1) != '\\')
{
if (*p == '|' || *p == '\n')
return p + 1;
return NULL; /* It's a comment */
}
}
++p;
}
}
/* no arguments allowed */
if (!(argt & EXTRA) && *arg != NUL &&
vim_strchr((char_u *)"|\"", *arg) == NULL)
return NULL;
/* Find start of last argument (argument just before cursor): */
p = buff + STRLEN(buff);
while (p != arg && *p != ' ' && *p != TAB)
p--;
if (*p == ' ' || *p == TAB)
p++;
expand_pattern = p;
if (argt & XFILE)
{
int in_quote = FALSE;
char_u *bow = NULL; /* Beginning of word */
/*
* Allow spaces within back-quotes to count as part of the argument
* being expanded.
*/
expand_pattern = skipwhite(arg);
for (p = expand_pattern; *p; ++p)
{
if (*p == '\\' && p[1])
++p;
#ifdef SPACE_IN_FILENAME
else if (vim_iswhite(*p) && (!(argt & NOSPC) || usefilter))
#else
else if (vim_iswhite(*p))
#endif
{
p = skipwhite(p);
if (in_quote)
bow = p;
else
expand_pattern = p;
--p;
}
else if (*p == '`')
{
if (!in_quote)
{
expand_pattern = p;
bow = p + 1;
}
in_quote = !in_quote;
}
}
/*
* If we are still inside the quotes, and we passed a space, just
* expand from there.
*/
if (bow != NULL && in_quote)
expand_pattern = bow;
expand_context = EXPAND_FILES;
}
/*
* 6. switch on command name
*/
switch (cmdidx)
{
case CMD_cd:
case CMD_chdir:
expand_context = EXPAND_DIRECTORIES;
break;
#ifdef USE_BROWSE
case CMD_browse:
#endif
case CMD_confirm:
return arg;
case CMD_global:
case CMD_vglobal:
delim = *arg; /* get the delimiter */
if (delim)
++arg; /* skip delimiter if there is one */
while (arg[0] != NUL && arg[0] != delim)
{
if (arg[0] == '\\' && arg[1] != NUL)
++arg;
++arg;
}
if (arg[0] != NUL)
return arg + 1;
break;
case CMD_and:
case CMD_substitute:
delim = *arg;
if (delim)
++arg;
for (i = 0; i < 2; i++)
{
while (arg[0] != NUL && arg[0] != delim)
{
if (arg[0] == '\\' && arg[1] != NUL)
++arg;
++arg;
}
if (arg[0] != NUL) /* skip delimiter */
++arg;
}
while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL)
++arg;
if (arg[0] != NUL)
return arg;
break;
case CMD_isearch:
case CMD_dsearch:
case CMD_ilist:
case CMD_dlist:
case CMD_ijump:
case CMD_djump:
case CMD_isplit:
case CMD_dsplit:
arg = skipwhite(skipdigits(arg)); /* skip count */
if (*arg == '/') /* Match regexp, not just whole words */
{
for (++arg; *arg && *arg != '/'; arg++)
if (*arg == '\\' && arg[1] != NUL)
arg++;
if (*arg)
{
arg = skipwhite(arg + 1);
/* Check for trailing illegal characters */
if (*arg && vim_strchr((char_u *)"|\"\n", *arg) == NULL)
expand_context = EXPAND_NOTHING;
else
return arg;
}
}
break;
#ifdef AUTOCMD
case CMD_autocmd:
return set_context_in_autocmd(arg, FALSE);
case CMD_doautocmd:
return set_context_in_autocmd(arg, TRUE);
#endif
case CMD_set:
set_context_in_set_cmd(arg);
break;
case CMD_tag:
case CMD_stag:
case CMD_tselect:
case CMD_stselect:
case CMD_tjump:
case CMD_stjump:
expand_context = EXPAND_TAGS;
expand_pattern = arg;
break;
case CMD_help:
expand_context = EXPAND_HELP;
expand_pattern = arg;
break;
case CMD_augroup:
expand_context = EXPAND_AUGROUP;
expand_pattern = arg;
break;
#ifdef SYNTAX_HL
case CMD_syntax:
set_context_in_syntax_cmd(arg);
break;
#endif
#ifdef WANT_EVAL
case CMD_unlet:
while ((expand_pattern = vim_strchr(arg, ' ')) != NULL)
arg = expand_pattern + 1;
expand_context = EXPAND_USER_VARS;
expand_pattern = arg;
break;
case CMD_echohl:
expand_context = EXPAND_HIGHLIGHT;
expand_pattern = arg;
break;
#endif
case CMD_highlight:
set_context_in_highlight_cmd(arg);
break;
case CMD_bdelete:
case CMD_bunload:
while ((expand_pattern = vim_strchr(arg, ' ')) != NULL)
arg = expand_pattern + 1;
case CMD_buffer:
case CMD_sbuffer:
expand_context = EXPAND_BUFFERS;
expand_pattern = arg;
break;
#ifdef USER_COMMANDS
case CMD_USER:
if (compl != EXPAND_NOTHING)
{
#ifdef USE_GUI
if (compl == EXPAND_MENUS)
return gui_set_context_in_menu_cmd(cmd, arg, forceit);
#endif
if (compl == EXPAND_COMMANDS)
return arg;
while ((expand_pattern = vim_strchr(arg, ' ')) != NULL)
arg = expand_pattern + 1;
expand_context = compl;
expand_pattern = arg;
}
break;
#endif
#ifdef USE_GUI
case CMD_menu: case CMD_noremenu: case CMD_unmenu:
case CMD_amenu: case CMD_anoremenu: case CMD_aunmenu:
case CMD_nmenu: case CMD_nnoremenu: case CMD_nunmenu:
case CMD_vmenu: case CMD_vnoremenu: case CMD_vunmenu:
case CMD_omenu: case CMD_onoremenu: case CMD_ounmenu:
case CMD_imenu: case CMD_inoremenu: case CMD_iunmenu:
case CMD_cmenu: case CMD_cnoremenu: case CMD_cunmenu:
case CMD_tmenu: case CMD_tunmenu:
case CMD_tearoff:
return gui_set_context_in_menu_cmd(cmd, arg, forceit);
#endif
default:
break;
}
return NULL;
}
/*
* get a single EX address
*
* Set ptr to the next character after the part that was interpreted.
* Set ptr to NULL when an error is encountered.
*
* Return MAXLNUM when no Ex address was found.
*/
static linenr_t
get_address(ptr, skip)
char_u **ptr;
int skip; /* only skip the address, don't use it */
{
int c;
int i;
long n;
char_u *cmd;
FPOS pos;
FPOS *fp;
linenr_t lnum;
cmd = skipwhite(*ptr);
lnum = MAXLNUM;
do
{
switch (*cmd)
{
case '.': /* '.' - Cursor position */
++cmd;
lnum = curwin->w_cursor.lnum;
break;
case '$': /* '$' - last line */
++cmd;
lnum = curbuf->b_ml.ml_line_count;
break;
case '\'': /* ''' - mark */
if (*++cmd == NUL)
{
cmd = NULL;
goto error;
}
if (!skip)
{
fp = getmark(*cmd, FALSE);
++cmd;
if (check_mark(fp) == FAIL)
{
cmd = NULL;
goto error;
}
lnum = fp->lnum;
}
break;
case '/':
case '?': /* '/' or '?' - search */
c = *cmd++;
if (skip) /* skip "/pat/" */
{
cmd = skip_regexp(cmd, c, (int)p_magic);
if (*cmd == c)
++cmd;
}
else
{
pos = curwin->w_cursor; /* save curwin->w_cursor */
/*
* When '/' or '?' follows another address, start
* from there.
*/
if (lnum != MAXLNUM)
curwin->w_cursor.lnum = lnum;
/*
* Start a forward search at the end of the line.
* Start a backward search at the start of the line.
* This makes sure we never match in the current
* line, and can match anywhere in the
* next/previous line.
*/
if (c == '/')
curwin->w_cursor.col = MAXCOL;
else
curwin->w_cursor.col = 0;
searchcmdlen = 0;
if (!do_search(NULL, c, cmd, 1L,
SEARCH_HIS + SEARCH_MSG + SEARCH_START))
{
curwin->w_cursor = pos;
cmd = NULL;
goto error;
}
lnum = curwin->w_cursor.l
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -