# HG changeset patch # User Bram Moolenaar # Date 1566588604 -7200 # Node ID fd6c8dc33152deb8a3a047352130fa5b00cde183 # Parent 6170a2c5faaf8f2d2098f5b17acd4214729956ba patch 8.1.1914: command line expansion code is spread out Commit: https://github.com/vim/vim/commit/d019039ccd7cbeae8923db20383a241d7fc77e2c Author: Bram Moolenaar Date: Fri Aug 23 21:17:35 2019 +0200 patch 8.1.1914: command line expansion code is spread out Problem: Command line expansion code is spread out. Solution: Move set_one_cmd_context(). (Yegappan Lakshmanan, closes https://github.com/vim/vim/issues/4855) diff --git a/src/cmdexpand.c b/src/cmdexpand.c --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -959,6 +959,812 @@ set_expand_context(expand_T *xp) set_cmd_context(xp, ccline->cmdbuff, ccline->cmdlen, ccline->cmdpos, TRUE); } +/* + * This is all pretty much copied from do_one_cmd(), with all the extra stuff + * we don't need/want deleted. Maybe this could be done better if we didn't + * repeat all this stuff. The only problem is that they may not stay + * perfectly compatible with each other, but then the command line syntax + * probably won't change that much -- webb. + */ + static char_u * +set_one_cmd_context( + expand_T *xp, + char_u *buff) // buffer for command string +{ + char_u *p; + char_u *cmd, *arg; + int len = 0; + exarg_T ea; + int compl = EXPAND_NOTHING; + int delim; + int forceit = FALSE; + int usefilter = FALSE; // filter instead of file name + + ExpandInit(xp); + xp->xp_pattern = buff; + xp->xp_context = EXPAND_COMMANDS; // Default until we get past command + ea.argt = 0; + + // 1. skip comment lines and leading space, colons or bars + for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++) + ; + xp->xp_pattern = cmd; + + if (*cmd == NUL) + return NULL; + if (*cmd == '"') // ignore comment lines + { + xp->xp_context = EXPAND_NOTHING; + return NULL; + } + + // 3. Skip over the range to find the command. + cmd = skip_range(cmd, &xp->xp_context); + xp->xp_pattern = cmd; + if (*cmd == NUL) + return NULL; + if (*cmd == '"') + { + xp->xp_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, but + // do accept "keepmarks", "keepalt" and "keepjumps". + // - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r' + if (*cmd == 'k' && cmd[1] != 'e') + { + ea.cmdidx = CMD_k; + p = cmd + 1; + } + else + { + p = cmd; + while (ASCII_ISALPHA(*p) || *p == '*') // Allow * wild card + ++p; + // a user command may contain digits + if (ASCII_ISUPPER(cmd[0])) + while (ASCII_ISALNUM(*p) || *p == '*') + ++p; + // for python 3.x: ":py3*" commands completion + if (cmd[0] == 'p' && cmd[1] == 'y' && p == cmd + 2 && *p == '3') + { + ++p; + while (ASCII_ISALPHA(*p) || *p == '*') + ++p; + } + // check for non-alpha command + if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL) + ++p; + len = (int)(p - cmd); + + if (len == 0) + { + xp->xp_context = EXPAND_UNSUCCESSFUL; + return NULL; + } + + ea.cmdidx = excmd_get_cmdidx(cmd, len); + + if (cmd[0] >= 'A' && cmd[0] <= 'Z') + while (ASCII_ISALNUM(*p) || *p == '*') // Allow * wild card + ++p; + } + + // If the cursor is touching the command, and it ends in an alpha-numeric + // character, complete the command name. + if (*p == NUL && ASCII_ISALNUM(p[-1])) + return NULL; + + if (ea.cmdidx == CMD_SIZE) + { + if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL) + { + ea.cmdidx = CMD_substitute; + p = cmd + 1; + } + else if (cmd[0] >= 'A' && cmd[0] <= 'Z') + { + ea.cmd = cmd; + p = find_ucmd(&ea, p, NULL, xp, &compl); + if (p == NULL) + ea.cmdidx = CMD_SIZE; // ambiguous user command + } + } + if (ea.cmdidx == CMD_SIZE) + { + // Not still touching the command and it was an illegal one + xp->xp_context = EXPAND_UNSUCCESSFUL; + return NULL; + } + + xp->xp_context = EXPAND_NOTHING; // Default now that we're past command + + if (*p == '!') // forced commands + { + forceit = TRUE; + ++p; + } + + // 6. parse arguments + if (!IS_USER_CMDIDX(ea.cmdidx)) + ea.argt = excmd_get_argt(ea.cmdidx); + + arg = skipwhite(p); + + if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) + { + if (*arg == '>') // append + { + if (*++arg == '>') + ++arg; + arg = skipwhite(arg); + } + else if (*arg == '!' && ea.cmdidx == CMD_write) // :w !filter + { + ++arg; + usefilter = TRUE; + } + } + + if (ea.cmdidx == CMD_read) + { + usefilter = forceit; // :r! filter if forced + if (*arg == '!') // :r !filter + { + ++arg; + usefilter = TRUE; + } + } + + if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) + { + while (*arg == *cmd) // allow any number of '>' or '<' + ++arg; + arg = skipwhite(arg); + } + + // Does command allow "+command"? + if ((ea.argt & EX_CMDARG) && !usefilter && *arg == '+') + { + // Check if we're in the +command + p = arg + 1; + arg = skip_cmd_arg(arg, FALSE); + + // 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 ((ea.argt & EX_TRLBAR) && !usefilter) + { + p = arg; + // ":redir @" is not the start of a comment + if (ea.cmdidx == CMD_redir && p[0] == '@' && p[1] == '"') + p += 2; + while (*p) + { + if (*p == Ctrl_V) + { + if (p[1] != NUL) + ++p; + } + else if ( (*p == '"' && !(ea.argt & EX_NOTRLCOM)) + || *p == '|' || *p == '\n') + { + if (*(p - 1) != '\\') + { + if (*p == '|' || *p == '\n') + return p + 1; + return NULL; // It's a comment + } + } + MB_PTR_ADV(p); + } + } + + if (!(ea.argt & EX_EXTRA) && *arg != NUL + && vim_strchr((char_u *)"|\"", *arg) == NULL) + // no arguments allowed but there is something + return NULL; + + // Find start of last argument (argument just before cursor): + p = buff; + xp->xp_pattern = p; + len = (int)STRLEN(buff); + while (*p && p < buff + len) + { + if (*p == ' ' || *p == TAB) + { + // argument starts after a space + xp->xp_pattern = ++p; + } + else + { + if (*p == '\\' && *(p + 1) != NUL) + ++p; // skip over escaped character + MB_PTR_ADV(p); + } + } + + if (ea.argt & EX_XFILE) + { + int c; + 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. + xp->xp_pattern = skipwhite(arg); + p = xp->xp_pattern; + while (*p != NUL) + { + if (has_mbyte) + c = mb_ptr2char(p); + else + c = *p; + if (c == '\\' && p[1] != NUL) + ++p; + else if (c == '`') + { + if (!in_quote) + { + xp->xp_pattern = p; + bow = p + 1; + } + in_quote = !in_quote; + } + // An argument can contain just about everything, except + // characters that end the command and white space. + else if (c == '|' || c == '\n' || c == '"' || (VIM_ISWHITE(c) +#ifdef SPACE_IN_FILENAME + && (!(ea.argt & EX_NOSPC) || usefilter) +#endif + )) + { + len = 0; // avoid getting stuck when space is in 'isfname' + while (*p != NUL) + { + if (has_mbyte) + c = mb_ptr2char(p); + else + c = *p; + if (c == '`' || vim_isfilec_or_wc(c)) + break; + if (has_mbyte) + len = (*mb_ptr2len)(p); + else + len = 1; + MB_PTR_ADV(p); + } + if (in_quote) + bow = p; + else + xp->xp_pattern = p; + p -= len; + } + MB_PTR_ADV(p); + } + + // If we are still inside the quotes, and we passed a space, just + // expand from there. + if (bow != NULL && in_quote) + xp->xp_pattern = bow; + xp->xp_context = EXPAND_FILES; + + // For a shell command more chars need to be escaped. + if (usefilter || ea.cmdidx == CMD_bang || ea.cmdidx == CMD_terminal) + { +#ifndef BACKSLASH_IN_FILENAME + xp->xp_shell = TRUE; +#endif + // When still after the command name expand executables. + if (xp->xp_pattern == skipwhite(arg)) + xp->xp_context = EXPAND_SHELLCMD; + } + + // Check for environment variable + if (*xp->xp_pattern == '$' +#if defined(MSWIN) + || *xp->xp_pattern == '%' +#endif + ) + { + for (p = xp->xp_pattern + 1; *p != NUL; ++p) + if (!vim_isIDc(*p)) + break; + if (*p == NUL) + { + xp->xp_context = EXPAND_ENV_VARS; + ++xp->xp_pattern; + // Avoid that the assignment uses EXPAND_FILES again. + if (compl != EXPAND_USER_DEFINED && compl != EXPAND_USER_LIST) + compl = EXPAND_ENV_VARS; + } + } + // Check for user names + if (*xp->xp_pattern == '~') + { + for (p = xp->xp_pattern + 1; *p != NUL && *p != '/'; ++p) + ; + // Complete ~user only if it partially matches a user name. + // A full match ~user will be replaced by user's home + // directory i.e. something like ~user -> /home/user/ + if (*p == NUL && p > xp->xp_pattern + 1 + && match_user(xp->xp_pattern + 1) >= 1) + { + xp->xp_context = EXPAND_USER; + ++xp->xp_pattern; + } + } + } + + // 6. Switch on command name. + switch (ea.cmdidx) + { + case CMD_find: + case CMD_sfind: + case CMD_tabfind: + if (xp->xp_context == EXPAND_FILES) + xp->xp_context = EXPAND_FILES_IN_PATH; + break; + case CMD_cd: + case CMD_chdir: + case CMD_tcd: + case CMD_tchdir: + case CMD_lcd: + case CMD_lchdir: + if (xp->xp_context == EXPAND_FILES) + xp->xp_context = EXPAND_DIRECTORIES; + break; + case CMD_help: + xp->xp_context = EXPAND_HELP; + xp->xp_pattern = arg; + break; + + // Command modifiers: return the argument. + // Also for commands with an argument that is a command. + case CMD_aboveleft: + case CMD_argdo: + case CMD_belowright: + case CMD_botright: + case CMD_browse: + case CMD_bufdo: + case CMD_cdo: + case CMD_cfdo: + case CMD_confirm: + case CMD_debug: + case CMD_folddoclosed: + case CMD_folddoopen: + case CMD_hide: + case CMD_keepalt: + case CMD_keepjumps: + case CMD_keepmarks: + case CMD_keeppatterns: + case CMD_ldo: + case CMD_leftabove: + case CMD_lfdo: + case CMD_lockmarks: + case CMD_noautocmd: + case CMD_noswapfile: + case CMD_rightbelow: + case CMD_sandbox: + case CMD_silent: + case CMD_tab: + case CMD_tabdo: + case CMD_topleft: + case CMD_verbose: + case CMD_vertical: + case CMD_windo: + return arg; + + case CMD_filter: + if (*arg != NUL) + arg = skip_vimgrep_pat(arg, NULL, NULL); + if (arg == NULL || *arg == NUL) + { + xp->xp_context = EXPAND_NOTHING; + return NULL; + } + return skipwhite(arg); + +#ifdef FEAT_SEARCH_EXTRA + case CMD_match: + if (*arg == NUL || !ends_excmd(*arg)) + { + // also complete "None" + set_context_in_echohl_cmd(xp, arg); + arg = skipwhite(skiptowhite(arg)); + if (*arg != NUL) + { + xp->xp_context = EXPAND_NOTHING; + arg = skip_regexp(arg + 1, *arg, p_magic, NULL); + } + } + return find_nextcmd(arg); +#endif + + // All completion for the +cmdline_compl feature goes here. + + case CMD_command: + return set_context_in_user_cmd(xp, arg); + + case CMD_delcommand: + xp->xp_context = EXPAND_USER_COMMANDS; + xp->xp_pattern = arg; + break; + + 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) + { + // skip "from" part + ++arg; + arg = skip_regexp(arg, delim, p_magic, NULL); + } + // skip "to" part + 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_psearch: + 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) + xp->xp_context = EXPAND_NOTHING; + else + return arg; + } + } + break; + + case CMD_autocmd: + return set_context_in_autocmd(xp, arg, FALSE); + case CMD_doautocmd: + case CMD_doautoall: + return set_context_in_autocmd(xp, arg, TRUE); + case CMD_set: + set_context_in_set_cmd(xp, arg, 0); + break; + case CMD_setglobal: + set_context_in_set_cmd(xp, arg, OPT_GLOBAL); + break; + case CMD_setlocal: + set_context_in_set_cmd(xp, arg, OPT_LOCAL); + break; + case CMD_tag: + case CMD_stag: + case CMD_ptag: + case CMD_ltag: + case CMD_tselect: + case CMD_stselect: + case CMD_ptselect: + case CMD_tjump: + case CMD_stjump: + case CMD_ptjump: + if (*p_wop != NUL) + xp->xp_context = EXPAND_TAGS_LISTFILES; + else + xp->xp_context = EXPAND_TAGS; + xp->xp_pattern = arg; + break; + case CMD_augroup: + xp->xp_context = EXPAND_AUGROUP; + xp->xp_pattern = arg; + break; +#ifdef FEAT_SYN_HL + case CMD_syntax: + set_context_in_syntax_cmd(xp, arg); + break; +#endif +#ifdef FEAT_EVAL + case CMD_let: + case CMD_if: + case CMD_elseif: + case CMD_while: + case CMD_for: + case CMD_echo: + case CMD_echon: + case CMD_execute: + case CMD_echomsg: + case CMD_echoerr: + case CMD_call: + case CMD_return: + case CMD_cexpr: + case CMD_caddexpr: + case CMD_cgetexpr: + case CMD_lexpr: + case CMD_laddexpr: + case CMD_lgetexpr: + set_context_for_expression(xp, arg, ea.cmdidx); + break; + + case CMD_unlet: + while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) + arg = xp->xp_pattern + 1; + + xp->xp_context = EXPAND_USER_VARS; + xp->xp_pattern = arg; + + if (*xp->xp_pattern == '$') + { + xp->xp_context = EXPAND_ENV_VARS; + ++xp->xp_pattern; + } + + break; + + case CMD_function: + case CMD_delfunction: + xp->xp_context = EXPAND_USER_FUNC; + xp->xp_pattern = arg; + break; + + case CMD_echohl: + set_context_in_echohl_cmd(xp, arg); + break; +#endif + case CMD_highlight: + set_context_in_highlight_cmd(xp, arg); + break; +#ifdef FEAT_CSCOPE + case CMD_cscope: + case CMD_lcscope: + case CMD_scscope: + set_context_in_cscope_cmd(xp, arg, ea.cmdidx); + break; +#endif +#ifdef FEAT_SIGNS + case CMD_sign: + set_context_in_sign_cmd(xp, arg); + break; +#endif + case CMD_bdelete: + case CMD_bwipeout: + case CMD_bunload: + while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) + arg = xp->xp_pattern + 1; + // FALLTHROUGH + case CMD_buffer: + case CMD_sbuffer: + case CMD_checktime: + xp->xp_context = EXPAND_BUFFERS; + xp->xp_pattern = arg; + break; + + case CMD_USER: + case CMD_USER_BUF: + if (compl != EXPAND_NOTHING) + { + // EX_XFILE: file names are handled above + if (!(ea.argt & EX_XFILE)) + { +#ifdef FEAT_MENU + if (compl == EXPAND_MENUS) + return set_context_in_menu_cmd(xp, cmd, arg, forceit); +#endif + if (compl == EXPAND_COMMANDS) + return arg; + if (compl == EXPAND_MAPPINGS) + return set_context_in_map_cmd(xp, (char_u *)"map", + arg, forceit, FALSE, FALSE, CMD_map); + // Find start of last argument. + p = arg; + while (*p) + { + if (*p == ' ') + // argument starts after a space + arg = p + 1; + else if (*p == '\\' && *(p + 1) != NUL) + ++p; // skip over escaped character + MB_PTR_ADV(p); + } + xp->xp_pattern = arg; + } + xp->xp_context = compl; + } + break; + + case CMD_map: case CMD_noremap: + case CMD_nmap: case CMD_nnoremap: + case CMD_vmap: case CMD_vnoremap: + case CMD_omap: case CMD_onoremap: + case CMD_imap: case CMD_inoremap: + case CMD_cmap: case CMD_cnoremap: + case CMD_lmap: case CMD_lnoremap: + case CMD_smap: case CMD_snoremap: + case CMD_tmap: case CMD_tnoremap: + case CMD_xmap: case CMD_xnoremap: + return set_context_in_map_cmd(xp, cmd, arg, forceit, + FALSE, FALSE, ea.cmdidx); + case CMD_unmap: + case CMD_nunmap: + case CMD_vunmap: + case CMD_ounmap: + case CMD_iunmap: + case CMD_cunmap: + case CMD_lunmap: + case CMD_sunmap: + case CMD_tunmap: + case CMD_xunmap: + return set_context_in_map_cmd(xp, cmd, 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_tmapclear: + case CMD_xmapclear: + xp->xp_context = EXPAND_MAPCLEAR; + xp->xp_pattern = arg; + break; + + case CMD_abbreviate: case CMD_noreabbrev: + case CMD_cabbrev: case CMD_cnoreabbrev: + case CMD_iabbrev: case CMD_inoreabbrev: + return set_context_in_map_cmd(xp, cmd, arg, forceit, + TRUE, FALSE, ea.cmdidx); + case CMD_unabbreviate: + case CMD_cunabbrev: + case CMD_iunabbrev: + return set_context_in_map_cmd(xp, cmd, arg, forceit, + TRUE, TRUE, ea.cmdidx); +#ifdef FEAT_MENU + 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_tlmenu: case CMD_tlnoremenu: case CMD_tlunmenu: + case CMD_tmenu: case CMD_tunmenu: + case CMD_popup: case CMD_tearoff: case CMD_emenu: + return set_context_in_menu_cmd(xp, cmd, arg, forceit); +#endif + + case CMD_colorscheme: + xp->xp_context = EXPAND_COLORS; + xp->xp_pattern = arg; + break; + + case CMD_compiler: + xp->xp_context = EXPAND_COMPILER; + xp->xp_pattern = arg; + break; + + case CMD_ownsyntax: + xp->xp_context = EXPAND_OWNSYNTAX; + xp->xp_pattern = arg; + break; + + case CMD_setfiletype: + xp->xp_context = EXPAND_FILETYPE; + xp->xp_pattern = arg; + break; + + case CMD_packadd: + xp->xp_context = EXPAND_PACKADD; + xp->xp_pattern = arg; + break; + +#if defined(HAVE_LOCALE_H) || defined(X_LOCALE) + case CMD_language: + p = skiptowhite(arg); + if (*p == NUL) + { + xp->xp_context = EXPAND_LANGUAGE; + xp->xp_pattern = arg; + } + else + { + if ( STRNCMP(arg, "messages", p - arg) == 0 + || STRNCMP(arg, "ctype", p - arg) == 0 + || STRNCMP(arg, "time", p - arg) == 0) + { + xp->xp_context = EXPAND_LOCALES; + xp->xp_pattern = skipwhite(p); + } + else + xp->xp_context = EXPAND_NOTHING; + } + break; +#endif +#if defined(FEAT_PROFILE) + case CMD_profile: + set_context_in_profile_cmd(xp, arg); + break; +#endif + case CMD_behave: + xp->xp_context = EXPAND_BEHAVE; + xp->xp_pattern = arg; + break; + + case CMD_messages: + xp->xp_context = EXPAND_MESSAGES; + xp->xp_pattern = arg; + break; + + case CMD_history: + xp->xp_context = EXPAND_HISTORY; + xp->xp_pattern = arg; + break; +#if defined(FEAT_PROFILE) + case CMD_syntime: + xp->xp_context = EXPAND_SYNTIME; + xp->xp_pattern = arg; + break; +#endif + + case CMD_argdelete: + while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) + arg = xp->xp_pattern + 1; + xp->xp_context = EXPAND_ARGLIST; + xp->xp_pattern = arg; + break; + + default: + break; + } + return NULL; +} + void set_cmd_context( expand_T *xp, @@ -1115,6 +1921,40 @@ cleanup_help_tags(int num_file, char_u * #endif /* + * Function given to ExpandGeneric() to obtain the possible arguments of the + * ":behave {mswin,xterm}" command. + */ + static char_u * +get_behave_arg(expand_T *xp UNUSED, int idx) +{ + if (idx == 0) + return (char_u *)"mswin"; + if (idx == 1) + return (char_u *)"xterm"; + return NULL; +} + +/* + * Function given to ExpandGeneric() to obtain the possible arguments of the + * ":messages {clear}" command. + */ + static char_u * +get_messages_arg(expand_T *xp UNUSED, int idx) +{ + if (idx == 0) + return (char_u *)"clear"; + return NULL; +} + + static char_u * +get_mapclear_arg(expand_T *xp UNUSED, int idx) +{ + if (idx == 0) + return (char_u *)""; + return NULL; +} + +/* * Do the expansion based on xp->xp_context and "pat". */ static int diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -44,7 +44,6 @@ static void ex_bprevious(exarg_T *eap); static void ex_brewind(exarg_T *eap); static void ex_blast(exarg_T *eap); static char_u *getargcmd(char_u **); -static char_u *skip_cmd_arg(char_u *p, int rembs); static int getargopt(exarg_T *eap); #ifndef FEAT_QUICKFIX # define ex_make ex_ni @@ -3307,833 +3306,23 @@ cmd_exists(char_u *name) } #endif -/* - * This is all pretty much copied from do_one_cmd(), with all the extra stuff - * we don't need/want deleted. Maybe this could be done better if we didn't - * repeat all this stuff. The only problem is that they may not stay - * perfectly compatible with each other, but then the command line syntax - * probably won't change that much -- webb. - */ - char_u * -set_one_cmd_context( - expand_T *xp, - char_u *buff) /* buffer for command string */ -{ - char_u *p; - char_u *cmd, *arg; - int len = 0; - exarg_T ea; - int compl = EXPAND_NOTHING; - int delim; - int forceit = FALSE; - int usefilter = FALSE; /* filter instead of file name */ - - ExpandInit(xp); - xp->xp_pattern = buff; - xp->xp_context = EXPAND_COMMANDS; /* Default until we get past command */ - ea.argt = 0; - -/* - * 1. skip comment lines and leading space, colons or bars - */ - for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++) - ; - xp->xp_pattern = cmd; - - if (*cmd == NUL) - return NULL; - if (*cmd == '"') /* ignore comment lines */ - { - xp->xp_context = EXPAND_NOTHING; - return NULL; - } - -/* - * 3. Skip over the range to find the command. - */ - cmd = skip_range(cmd, &xp->xp_context); - xp->xp_pattern = cmd; - if (*cmd == NUL) - return NULL; - if (*cmd == '"') - { - xp->xp_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, but - * do accept "keepmarks", "keepalt" and "keepjumps". - * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r' - */ - if (*cmd == 'k' && cmd[1] != 'e') - { - ea.cmdidx = CMD_k; - p = cmd + 1; - } - else - { - p = cmd; - while (ASCII_ISALPHA(*p) || *p == '*') /* Allow * wild card */ - ++p; - /* a user command may contain digits */ - if (ASCII_ISUPPER(cmd[0])) - while (ASCII_ISALNUM(*p) || *p == '*') - ++p; - /* for python 3.x: ":py3*" commands completion */ - if (cmd[0] == 'p' && cmd[1] == 'y' && p == cmd + 2 && *p == '3') - { - ++p; - while (ASCII_ISALPHA(*p) || *p == '*') - ++p; - } - /* check for non-alpha command */ - if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL) - ++p; - len = (int)(p - cmd); - - if (len == 0) - { - xp->xp_context = EXPAND_UNSUCCESSFUL; - return NULL; - } - for (ea.cmdidx = (cmdidx_T)0; (int)ea.cmdidx < (int)CMD_SIZE; - ea.cmdidx = (cmdidx_T)((int)ea.cmdidx + 1)) - if (STRNCMP(cmdnames[(int)ea.cmdidx].cmd_name, cmd, - (size_t)len) == 0) - break; - - if (cmd[0] >= 'A' && cmd[0] <= 'Z') - while (ASCII_ISALNUM(*p) || *p == '*') // Allow * wild card - ++p; - } - - /* - * If the cursor is touching the command, and it ends in an alpha-numeric - * character, complete the command name. - */ - if (*p == NUL && ASCII_ISALNUM(p[-1])) - return NULL; - - if (ea.cmdidx == CMD_SIZE) - { - if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL) - { - ea.cmdidx = CMD_substitute; - p = cmd + 1; - } - else if (cmd[0] >= 'A' && cmd[0] <= 'Z') - { - ea.cmd = cmd; - p = find_ucmd(&ea, p, NULL, xp, &compl); - if (p == NULL) - ea.cmdidx = CMD_SIZE; // ambiguous user command - } - } - if (ea.cmdidx == CMD_SIZE) - { - /* Not still touching the command and it was an illegal one */ - xp->xp_context = EXPAND_UNSUCCESSFUL; - return NULL; - } - - xp->xp_context = EXPAND_NOTHING; /* Default now that we're past command */ - - if (*p == '!') /* forced commands */ - { - forceit = TRUE; - ++p; - } - -/* - * 6. parse arguments - */ - if (!IS_USER_CMDIDX(ea.cmdidx)) - ea.argt = (long)cmdnames[(int)ea.cmdidx].cmd_argt; - - arg = skipwhite(p); - - if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) - { - if (*arg == '>') /* append */ - { - if (*++arg == '>') - ++arg; - arg = skipwhite(arg); - } - else if (*arg == '!' && ea.cmdidx == CMD_write) /* :w !filter */ - { - ++arg; - usefilter = TRUE; - } - } - - if (ea.cmdidx == CMD_read) - { - usefilter = forceit; /* :r! filter if forced */ - if (*arg == '!') /* :r !filter */ - { - ++arg; - usefilter = TRUE; - } - } - - if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) - { - while (*arg == *cmd) /* allow any number of '>' or '<' */ - ++arg; - arg = skipwhite(arg); - } - - /* Does command allow "+command"? */ - if ((ea.argt & EX_CMDARG) && !usefilter && *arg == '+') - { - /* Check if we're in the +command */ - p = arg + 1; - arg = skip_cmd_arg(arg, FALSE); - - /* 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 ((ea.argt & EX_TRLBAR) && !usefilter) - { - p = arg; - /* ":redir @" is not the start of a comment */ - if (ea.cmdidx == CMD_redir && p[0] == '@' && p[1] == '"') - p += 2; - while (*p) - { - if (*p == Ctrl_V) - { - if (p[1] != NUL) - ++p; - } - else if ( (*p == '"' && !(ea.argt & EX_NOTRLCOM)) - || *p == '|' || *p == '\n') - { - if (*(p - 1) != '\\') - { - if (*p == '|' || *p == '\n') - return p + 1; - return NULL; /* It's a comment */ - } - } - MB_PTR_ADV(p); - } - } - - if (!(ea.argt & EX_EXTRA) && *arg != NUL - && vim_strchr((char_u *)"|\"", *arg) == NULL) - // no arguments allowed but there is something - return NULL; - - /* Find start of last argument (argument just before cursor): */ - p = buff; - xp->xp_pattern = p; - len = (int)STRLEN(buff); - while (*p && p < buff + len) - { - if (*p == ' ' || *p == TAB) - { - /* argument starts after a space */ - xp->xp_pattern = ++p; - } - else - { - if (*p == '\\' && *(p + 1) != NUL) - ++p; /* skip over escaped character */ - MB_PTR_ADV(p); - } - } - - if (ea.argt & EX_XFILE) - { - int c; - 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. - */ - xp->xp_pattern = skipwhite(arg); - p = xp->xp_pattern; - while (*p != NUL) - { - if (has_mbyte) - c = mb_ptr2char(p); - else - c = *p; - if (c == '\\' && p[1] != NUL) - ++p; - else if (c == '`') - { - if (!in_quote) - { - xp->xp_pattern = p; - bow = p + 1; - } - in_quote = !in_quote; - } - /* An argument can contain just about everything, except - * characters that end the command and white space. */ - else if (c == '|' || c == '\n' || c == '"' || (VIM_ISWHITE(c) -#ifdef SPACE_IN_FILENAME - && (!(ea.argt & EX_NOSPC) || usefilter) -#endif - )) - { - len = 0; /* avoid getting stuck when space is in 'isfname' */ - while (*p != NUL) - { - if (has_mbyte) - c = mb_ptr2char(p); - else - c = *p; - if (c == '`' || vim_isfilec_or_wc(c)) - break; - if (has_mbyte) - len = (*mb_ptr2len)(p); - else - len = 1; - MB_PTR_ADV(p); - } - if (in_quote) - bow = p; - else - xp->xp_pattern = p; - p -= len; - } - MB_PTR_ADV(p); - } - - /* - * If we are still inside the quotes, and we passed a space, just - * expand from there. - */ - if (bow != NULL && in_quote) - xp->xp_pattern = bow; - xp->xp_context = EXPAND_FILES; - - /* For a shell command more chars need to be escaped. */ - if (usefilter || ea.cmdidx == CMD_bang || ea.cmdidx == CMD_terminal) - { -#ifndef BACKSLASH_IN_FILENAME - xp->xp_shell = TRUE; -#endif - /* When still after the command name expand executables. */ - if (xp->xp_pattern == skipwhite(arg)) - xp->xp_context = EXPAND_SHELLCMD; - } - - /* Check for environment variable */ - if (*xp->xp_pattern == '$' -#if defined(MSWIN) - || *xp->xp_pattern == '%' -#endif - ) - { - for (p = xp->xp_pattern + 1; *p != NUL; ++p) - if (!vim_isIDc(*p)) - break; - if (*p == NUL) - { - xp->xp_context = EXPAND_ENV_VARS; - ++xp->xp_pattern; - /* Avoid that the assignment uses EXPAND_FILES again. */ - if (compl != EXPAND_USER_DEFINED && compl != EXPAND_USER_LIST) - compl = EXPAND_ENV_VARS; - } - } - /* Check for user names */ - if (*xp->xp_pattern == '~') - { - for (p = xp->xp_pattern + 1; *p != NUL && *p != '/'; ++p) - ; - /* Complete ~user only if it partially matches a user name. - * A full match ~user will be replaced by user's home - * directory i.e. something like ~user -> /home/user/ */ - if (*p == NUL && p > xp->xp_pattern + 1 - && match_user(xp->xp_pattern + 1) >= 1) - { - xp->xp_context = EXPAND_USER; - ++xp->xp_pattern; - } - } - } - -/* - * 6. Switch on command name. - */ - switch (ea.cmdidx) - { - case CMD_find: - case CMD_sfind: - case CMD_tabfind: - if (xp->xp_context == EXPAND_FILES) - xp->xp_context = EXPAND_FILES_IN_PATH; - break; - case CMD_cd: - case CMD_chdir: - case CMD_tcd: - case CMD_tchdir: - case CMD_lcd: - case CMD_lchdir: - if (xp->xp_context == EXPAND_FILES) - xp->xp_context = EXPAND_DIRECTORIES; - break; - case CMD_help: - xp->xp_context = EXPAND_HELP; - xp->xp_pattern = arg; + cmdidx_T +excmd_get_cmdidx(char_u *cmd, int len) +{ + cmdidx_T idx; + + for (idx = (cmdidx_T)0; (int)idx < (int)CMD_SIZE; + idx = (cmdidx_T)((int)idx + 1)) + if (STRNCMP(cmdnames[(int)idx].cmd_name, cmd, (size_t)len) == 0) break; - /* Command modifiers: return the argument. - * Also for commands with an argument that is a command. */ - case CMD_aboveleft: - case CMD_argdo: - case CMD_belowright: - case CMD_botright: - case CMD_browse: - case CMD_bufdo: - case CMD_cdo: - case CMD_cfdo: - case CMD_confirm: - case CMD_debug: - case CMD_folddoclosed: - case CMD_folddoopen: - case CMD_hide: - case CMD_keepalt: - case CMD_keepjumps: - case CMD_keepmarks: - case CMD_keeppatterns: - case CMD_ldo: - case CMD_leftabove: - case CMD_lfdo: - case CMD_lockmarks: - case CMD_noautocmd: - case CMD_noswapfile: - case CMD_rightbelow: - case CMD_sandbox: - case CMD_silent: - case CMD_tab: - case CMD_tabdo: - case CMD_topleft: - case CMD_verbose: - case CMD_vertical: - case CMD_windo: - return arg; - - case CMD_filter: - if (*arg != NUL) - arg = skip_vimgrep_pat(arg, NULL, NULL); - if (arg == NULL || *arg == NUL) - { - xp->xp_context = EXPAND_NOTHING; - return NULL; - } - return skipwhite(arg); - -#ifdef FEAT_SEARCH_EXTRA - case CMD_match: - if (*arg == NUL || !ends_excmd(*arg)) - { - /* also complete "None" */ - set_context_in_echohl_cmd(xp, arg); - arg = skipwhite(skiptowhite(arg)); - if (*arg != NUL) - { - xp->xp_context = EXPAND_NOTHING; - arg = skip_regexp(arg + 1, *arg, p_magic, NULL); - } - } - return find_nextcmd(arg); -#endif - -/* - * All completion for the +cmdline_compl feature goes here. - */ - - case CMD_command: - return set_context_in_user_cmd(xp, arg); - - case CMD_delcommand: - xp->xp_context = EXPAND_USER_COMMANDS; - xp->xp_pattern = arg; - break; - - 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) - { - /* skip "from" part */ - ++arg; - arg = skip_regexp(arg, delim, p_magic, NULL); - } - /* skip "to" part */ - 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_psearch: - 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) - xp->xp_context = EXPAND_NOTHING; - else - return arg; - } - } - break; - - case CMD_autocmd: - return set_context_in_autocmd(xp, arg, FALSE); - case CMD_doautocmd: - case CMD_doautoall: - return set_context_in_autocmd(xp, arg, TRUE); - case CMD_set: - set_context_in_set_cmd(xp, arg, 0); - break; - case CMD_setglobal: - set_context_in_set_cmd(xp, arg, OPT_GLOBAL); - break; - case CMD_setlocal: - set_context_in_set_cmd(xp, arg, OPT_LOCAL); - break; - case CMD_tag: - case CMD_stag: - case CMD_ptag: - case CMD_ltag: - case CMD_tselect: - case CMD_stselect: - case CMD_ptselect: - case CMD_tjump: - case CMD_stjump: - case CMD_ptjump: - if (*p_wop != NUL) - xp->xp_context = EXPAND_TAGS_LISTFILES; - else - xp->xp_context = EXPAND_TAGS; - xp->xp_pattern = arg; - break; - case CMD_augroup: - xp->xp_context = EXPAND_AUGROUP; - xp->xp_pattern = arg; - break; -#ifdef FEAT_SYN_HL - case CMD_syntax: - set_context_in_syntax_cmd(xp, arg); - break; -#endif -#ifdef FEAT_EVAL - case CMD_let: - case CMD_if: - case CMD_elseif: - case CMD_while: - case CMD_for: - case CMD_echo: - case CMD_echon: - case CMD_execute: - case CMD_echomsg: - case CMD_echoerr: - case CMD_call: - case CMD_return: - case CMD_cexpr: - case CMD_caddexpr: - case CMD_cgetexpr: - case CMD_lexpr: - case CMD_laddexpr: - case CMD_lgetexpr: - set_context_for_expression(xp, arg, ea.cmdidx); - break; - - case CMD_unlet: - while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) - arg = xp->xp_pattern + 1; - - xp->xp_context = EXPAND_USER_VARS; - xp->xp_pattern = arg; - - if (*xp->xp_pattern == '$') - { - xp->xp_context = EXPAND_ENV_VARS; - ++xp->xp_pattern; - } - - break; - - case CMD_function: - case CMD_delfunction: - xp->xp_context = EXPAND_USER_FUNC; - xp->xp_pattern = arg; - break; - - case CMD_echohl: - set_context_in_echohl_cmd(xp, arg); - break; -#endif - case CMD_highlight: - set_context_in_highlight_cmd(xp, arg); - break; -#ifdef FEAT_CSCOPE - case CMD_cscope: - case CMD_lcscope: - case CMD_scscope: - set_context_in_cscope_cmd(xp, arg, ea.cmdidx); - break; -#endif -#ifdef FEAT_SIGNS - case CMD_sign: - set_context_in_sign_cmd(xp, arg); - break; -#endif - case CMD_bdelete: - case CMD_bwipeout: - case CMD_bunload: - while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) - arg = xp->xp_pattern + 1; - /* FALLTHROUGH */ - case CMD_buffer: - case CMD_sbuffer: - case CMD_checktime: - xp->xp_context = EXPAND_BUFFERS; - xp->xp_pattern = arg; - break; - - case CMD_USER: - case CMD_USER_BUF: - if (compl != EXPAND_NOTHING) - { - // EX_XFILE: file names are handled above - if (!(ea.argt & EX_XFILE)) - { -#ifdef FEAT_MENU - if (compl == EXPAND_MENUS) - return set_context_in_menu_cmd(xp, cmd, arg, forceit); -#endif - if (compl == EXPAND_COMMANDS) - return arg; - if (compl == EXPAND_MAPPINGS) - return set_context_in_map_cmd(xp, (char_u *)"map", - arg, forceit, FALSE, FALSE, CMD_map); - // Find start of last argument. - p = arg; - while (*p) - { - if (*p == ' ') - // argument starts after a space - arg = p + 1; - else if (*p == '\\' && *(p + 1) != NUL) - ++p; // skip over escaped character - MB_PTR_ADV(p); - } - xp->xp_pattern = arg; - } - xp->xp_context = compl; - } - break; - - case CMD_map: case CMD_noremap: - case CMD_nmap: case CMD_nnoremap: - case CMD_vmap: case CMD_vnoremap: - case CMD_omap: case CMD_onoremap: - case CMD_imap: case CMD_inoremap: - case CMD_cmap: case CMD_cnoremap: - case CMD_lmap: case CMD_lnoremap: - case CMD_smap: case CMD_snoremap: - case CMD_tmap: case CMD_tnoremap: - case CMD_xmap: case CMD_xnoremap: - return set_context_in_map_cmd(xp, cmd, arg, forceit, - FALSE, FALSE, ea.cmdidx); - case CMD_unmap: - case CMD_nunmap: - case CMD_vunmap: - case CMD_ounmap: - case CMD_iunmap: - case CMD_cunmap: - case CMD_lunmap: - case CMD_sunmap: - case CMD_tunmap: - case CMD_xunmap: - return set_context_in_map_cmd(xp, cmd, 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_tmapclear: - case CMD_xmapclear: - xp->xp_context = EXPAND_MAPCLEAR; - xp->xp_pattern = arg; - break; - - case CMD_abbreviate: case CMD_noreabbrev: - case CMD_cabbrev: case CMD_cnoreabbrev: - case CMD_iabbrev: case CMD_inoreabbrev: - return set_context_in_map_cmd(xp, cmd, arg, forceit, - TRUE, FALSE, ea.cmdidx); - case CMD_unabbreviate: - case CMD_cunabbrev: - case CMD_iunabbrev: - return set_context_in_map_cmd(xp, cmd, arg, forceit, - TRUE, TRUE, ea.cmdidx); -#ifdef FEAT_MENU - 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_tlmenu: case CMD_tlnoremenu: case CMD_tlunmenu: - case CMD_tmenu: case CMD_tunmenu: - case CMD_popup: case CMD_tearoff: case CMD_emenu: - return set_context_in_menu_cmd(xp, cmd, arg, forceit); -#endif - - case CMD_colorscheme: - xp->xp_context = EXPAND_COLORS; - xp->xp_pattern = arg; - break; - - case CMD_compiler: - xp->xp_context = EXPAND_COMPILER; - xp->xp_pattern = arg; - break; - - case CMD_ownsyntax: - xp->xp_context = EXPAND_OWNSYNTAX; - xp->xp_pattern = arg; - break; - - case CMD_setfiletype: - xp->xp_context = EXPAND_FILETYPE; - xp->xp_pattern = arg; - break; - - case CMD_packadd: - xp->xp_context = EXPAND_PACKADD; - xp->xp_pattern = arg; - break; - -#if defined(HAVE_LOCALE_H) || defined(X_LOCALE) - case CMD_language: - p = skiptowhite(arg); - if (*p == NUL) - { - xp->xp_context = EXPAND_LANGUAGE; - xp->xp_pattern = arg; - } - else - { - if ( STRNCMP(arg, "messages", p - arg) == 0 - || STRNCMP(arg, "ctype", p - arg) == 0 - || STRNCMP(arg, "time", p - arg) == 0) - { - xp->xp_context = EXPAND_LOCALES; - xp->xp_pattern = skipwhite(p); - } - else - xp->xp_context = EXPAND_NOTHING; - } - break; -#endif -#if defined(FEAT_PROFILE) - case CMD_profile: - set_context_in_profile_cmd(xp, arg); - break; -#endif - case CMD_behave: - xp->xp_context = EXPAND_BEHAVE; - xp->xp_pattern = arg; - break; - - case CMD_messages: - xp->xp_context = EXPAND_MESSAGES; - xp->xp_pattern = arg; - break; - - case CMD_history: - xp->xp_context = EXPAND_HISTORY; - xp->xp_pattern = arg; - break; -#if defined(FEAT_PROFILE) - case CMD_syntime: - xp->xp_context = EXPAND_SYNTIME; - xp->xp_pattern = arg; - break; -#endif - - case CMD_argdelete: - while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) - arg = xp->xp_pattern + 1; - xp->xp_context = EXPAND_ARGLIST; - xp->xp_pattern = arg; - break; - - default: - break; - } - return NULL; + return idx; +} + + long +excmd_get_argt(cmdidx_T idx) +{ + return (long)cmdnames[(int)idx].cmd_argt; } /* @@ -5196,7 +4385,7 @@ getargcmd(char_u **argp) /* * Find end of "+command" argument. Skip over "\ " and "\\". */ - static char_u * + char_u * skip_cmd_arg( char_u *p, int rembs) /* TRUE to halve the number of backslashes */ @@ -9162,40 +8351,6 @@ ex_behave(exarg_T *eap) semsg(_(e_invarg2), eap->arg); } -/* - * Function given to ExpandGeneric() to obtain the possible arguments of the - * ":behave {mswin,xterm}" command. - */ - char_u * -get_behave_arg(expand_T *xp UNUSED, int idx) -{ - if (idx == 0) - return (char_u *)"mswin"; - if (idx == 1) - return (char_u *)"xterm"; - return NULL; -} - -/* - * Function given to ExpandGeneric() to obtain the possible arguments of the - * ":messages {clear}" command. - */ - char_u * -get_messages_arg(expand_T *xp UNUSED, int idx) -{ - if (idx == 0) - return (char_u *)"clear"; - return NULL; -} - - char_u * -get_mapclear_arg(expand_T *xp UNUSED, int idx) -{ - if (idx == 0) - return (char_u *)""; - return NULL; -} - static int filetype_detect = FALSE; static int filetype_plugin = FALSE; static int filetype_indent = FALSE; diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro --- a/src/proto/ex_docmd.pro +++ b/src/proto/ex_docmd.pro @@ -9,11 +9,13 @@ int parse_cmd_address(exarg_T *eap, char int checkforcmd(char_u **pp, char *cmd, int len); int modifier_len(char_u *cmd); int cmd_exists(char_u *name); -char_u *set_one_cmd_context(expand_T *xp, char_u *buff); +cmdidx_T excmd_get_cmdidx(char_u *cmd, int len); +long excmd_get_argt(cmdidx_T idx); char_u *skip_range(char_u *cmd, int *ctx); void ex_ni(exarg_T *eap); int expand_filename(exarg_T *eap, char_u **cmdlinep, char **errormsgp); void separate_nextcmd(exarg_T *eap); +char_u *skip_cmd_arg( char_u *p, int rembs); int get_bad_opt(char_u *p, exarg_T *eap); int ends_excmd(int c); char_u *find_nextcmd(char_u *p); @@ -48,9 +50,6 @@ char_u *expand_sfile(char_u *arg); int put_eol(FILE *fd); int put_line(FILE *fd, char *s); void dialog_msg(char_u *buff, char *format, char_u *fname); -char_u *get_behave_arg(expand_T *xp, int idx); -char_u *get_messages_arg(expand_T *xp, int idx); -char_u *get_mapclear_arg(expand_T *xp, int idx); void set_no_hlsearch(int flag); int is_loclist_cmd(int cmdidx); int get_pressedreturn(void); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -762,6 +762,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1914, +/**/ 1913, /**/ 1912,