summaryrefslogtreecommitdiff
path: root/data/vim/patches/8.1.1210
diff options
context:
space:
mode:
Diffstat (limited to 'data/vim/patches/8.1.1210')
-rw-r--r--data/vim/patches/8.1.12104639
1 files changed, 0 insertions, 4639 deletions
diff --git a/data/vim/patches/8.1.1210 b/data/vim/patches/8.1.1210
deleted file mode 100644
index 4405c63ae..000000000
--- a/data/vim/patches/8.1.1210
+++ /dev/null
@@ -1,4639 +0,0 @@
-To: vim_dev@googlegroups.com
-Subject: Patch 8.1.1210
-Fcc: outbox
-From: Bram Moolenaar <Bram@moolenaar.net>
-Mime-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-------------
-
-Patch 8.1.1210
-Problem: Support for user commands is spread out. No good reason to make
- user commands optional.
-Solution: Move user command support to usercmd.c. Always enable the
- user_commands feature.
-Files: src/usercmd.c, src/proto/usercmd.pro, Filelist, src/Make_bc5.mak,
- src/Make_cyg_ming.mak, src/Make_dice.mak, src/Make_ivc.mak,
- src/Make_manx.mak, src/Make_morph.mak, src/Make_mvc.mak,
- src/Make_sas.mak, src/Make_vms.mms, src/Makefile, src/README.md,
- src/buffer.c, src/eval.c, src/evalfunc.c, src/ex_cmds.h,
- src/ex_docmd.c, src/proto/ex_docmd.pro, src/ex_getln.c,
- src/feature.h, src/macros.h, src/misc2.c, src/proto.h,
- src/structs.h, src/version.c, runtime/doc/eval.txt,
- runtime/doc/various.txt
-
-
-*** ../vim-8.1.1209/src/usercmd.c 2019-04-27 12:58:18.994395422 +0200
---- src/usercmd.c 2019-04-27 12:54:00.423836989 +0200
-***************
-*** 0 ****
---- 1,1656 ----
-+ /* vi:set ts=8 sts=4 sw=4 noet:
-+ *
-+ * VIM - Vi IMproved by Bram Moolenaar
-+ *
-+ * Do ":help uganda" in Vim to read copying and usage conditions.
-+ * Do ":help credits" in Vim to see a list of people who contributed.
-+ * See README.txt for an overview of the Vim source code.
-+ */
-+
-+ /*
-+ * usercmd.c: User defined command support
-+ */
-+
-+ #include "vim.h"
-+
-+ typedef struct ucmd
-+ {
-+ char_u *uc_name; // The command name
-+ long_u uc_argt; // The argument type
-+ char_u *uc_rep; // The command's replacement string
-+ long uc_def; // The default value for a range/count
-+ int uc_compl; // completion type
-+ int uc_addr_type; // The command's address type
-+ # ifdef FEAT_EVAL
-+ sctx_T uc_script_ctx; // SCTX where the command was defined
-+ # ifdef FEAT_CMDL_COMPL
-+ char_u *uc_compl_arg; // completion argument if any
-+ # endif
-+ # endif
-+ } ucmd_T;
-+
-+ // List of all user commands.
-+ static garray_T ucmds = {0, 0, sizeof(ucmd_T), 4, NULL};
-+
-+ #define USER_CMD(i) (&((ucmd_T *)(ucmds.ga_data))[i])
-+ #define USER_CMD_GA(gap, i) (&((ucmd_T *)((gap)->ga_data))[i])
-+
-+ /*
-+ * List of names for completion for ":command" with the EXPAND_ flag.
-+ * Must be alphabetical for completion.
-+ */
-+ static struct
-+ {
-+ int expand;
-+ char *name;
-+ } command_complete[] =
-+ {
-+ {EXPAND_ARGLIST, "arglist"},
-+ {EXPAND_AUGROUP, "augroup"},
-+ {EXPAND_BEHAVE, "behave"},
-+ {EXPAND_BUFFERS, "buffer"},
-+ {EXPAND_COLORS, "color"},
-+ {EXPAND_COMMANDS, "command"},
-+ {EXPAND_COMPILER, "compiler"},
-+ #if defined(FEAT_CSCOPE)
-+ {EXPAND_CSCOPE, "cscope"},
-+ #endif
-+ #if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-+ {EXPAND_USER_DEFINED, "custom"},
-+ {EXPAND_USER_LIST, "customlist"},
-+ #endif
-+ {EXPAND_DIRECTORIES, "dir"},
-+ {EXPAND_ENV_VARS, "environment"},
-+ {EXPAND_EVENTS, "event"},
-+ {EXPAND_EXPRESSION, "expression"},
-+ {EXPAND_FILES, "file"},
-+ {EXPAND_FILES_IN_PATH, "file_in_path"},
-+ {EXPAND_FILETYPE, "filetype"},
-+ {EXPAND_FUNCTIONS, "function"},
-+ {EXPAND_HELP, "help"},
-+ {EXPAND_HIGHLIGHT, "highlight"},
-+ #if defined(FEAT_CMDHIST)
-+ {EXPAND_HISTORY, "history"},
-+ #endif
-+ #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
-+ {EXPAND_LOCALES, "locale"},
-+ #endif
-+ {EXPAND_MAPCLEAR, "mapclear"},
-+ {EXPAND_MAPPINGS, "mapping"},
-+ {EXPAND_MENUS, "menu"},
-+ {EXPAND_MESSAGES, "messages"},
-+ {EXPAND_OWNSYNTAX, "syntax"},
-+ #if defined(FEAT_PROFILE)
-+ {EXPAND_SYNTIME, "syntime"},
-+ #endif
-+ {EXPAND_SETTINGS, "option"},
-+ {EXPAND_PACKADD, "packadd"},
-+ {EXPAND_SHELLCMD, "shellcmd"},
-+ #if defined(FEAT_SIGNS)
-+ {EXPAND_SIGN, "sign"},
-+ #endif
-+ {EXPAND_TAGS, "tag"},
-+ {EXPAND_TAGS_LISTFILES, "tag_listfiles"},
-+ {EXPAND_USER, "user"},
-+ {EXPAND_USER_VARS, "var"},
-+ {0, NULL}
-+ };
-+
-+ /*
-+ * List of names of address types. Must be alphabetical for completion.
-+ */
-+ static struct
-+ {
-+ int expand;
-+ char *name;
-+ char *shortname;
-+ } addr_type_complete[] =
-+ {
-+ {ADDR_ARGUMENTS, "arguments", "arg"},
-+ {ADDR_LINES, "lines", "line"},
-+ {ADDR_LOADED_BUFFERS, "loaded_buffers", "load"},
-+ {ADDR_TABS, "tabs", "tab"},
-+ {ADDR_BUFFERS, "buffers", "buf"},
-+ {ADDR_WINDOWS, "windows", "win"},
-+ {ADDR_QUICKFIX, "quickfix", "qf"},
-+ {ADDR_OTHER, "other", "?"},
-+ {-1, NULL, NULL}
-+ };
-+
-+ #define UC_BUFFER 1 // -buffer: local to current buffer
-+
-+ /*
-+ * Search for a user command that matches "eap->cmd".
-+ * Return cmdidx in "eap->cmdidx", flags in "eap->argt", idx in "eap->useridx".
-+ * Return a pointer to just after the command.
-+ * Return NULL if there is no matching command.
-+ */
-+ char_u *
-+ find_ucmd(
-+ exarg_T *eap,
-+ char_u *p, // end of the command (possibly including count)
-+ int *full, // set to TRUE for a full match
-+ expand_T *xp, // used for completion, NULL otherwise
-+ int *compl UNUSED) // completion flags or NULL
-+ {
-+ int len = (int)(p - eap->cmd);
-+ int j, k, matchlen = 0;
-+ ucmd_T *uc;
-+ int found = FALSE;
-+ int possible = FALSE;
-+ char_u *cp, *np; // Point into typed cmd and test name
-+ garray_T *gap;
-+ int amb_local = FALSE; // Found ambiguous buffer-local command,
-+ // only full match global is accepted.
-+
-+ /*
-+ * Look for buffer-local user commands first, then global ones.
-+ */
-+ gap = &curbuf->b_ucmds;
-+ for (;;)
-+ {
-+ for (j = 0; j < gap->ga_len; ++j)
-+ {
-+ uc = USER_CMD_GA(gap, j);
-+ cp = eap->cmd;
-+ np = uc->uc_name;
-+ k = 0;
-+ while (k < len && *np != NUL && *cp++ == *np++)
-+ k++;
-+ if (k == len || (*np == NUL && vim_isdigit(eap->cmd[k])))
-+ {
-+ // If finding a second match, the command is ambiguous. But
-+ // not if a buffer-local command wasn't a full match and a
-+ // global command is a full match.
-+ if (k == len && found && *np != NUL)
-+ {
-+ if (gap == &ucmds)
-+ return NULL;
-+ amb_local = TRUE;
-+ }
-+
-+ if (!found || (k == len && *np == NUL))
-+ {
-+ // If we matched up to a digit, then there could
-+ // be another command including the digit that we
-+ // should use instead.
-+ if (k == len)
-+ found = TRUE;
-+ else
-+ possible = TRUE;
-+
-+ if (gap == &ucmds)
-+ eap->cmdidx = CMD_USER;
-+ else
-+ eap->cmdidx = CMD_USER_BUF;
-+ eap->argt = (long)uc->uc_argt;
-+ eap->useridx = j;
-+ eap->addr_type = uc->uc_addr_type;
-+
-+ # ifdef FEAT_CMDL_COMPL
-+ if (compl != NULL)
-+ *compl = uc->uc_compl;
-+ # ifdef FEAT_EVAL
-+ if (xp != NULL)
-+ {
-+ xp->xp_arg = uc->uc_compl_arg;
-+ xp->xp_script_ctx = uc->uc_script_ctx;
-+ xp->xp_script_ctx.sc_lnum += sourcing_lnum;
-+ }
-+ # endif
-+ # endif
-+ // Do not search for further abbreviations
-+ // if this is an exact match.
-+ matchlen = k;
-+ if (k == len && *np == NUL)
-+ {
-+ if (full != NULL)
-+ *full = TRUE;
-+ amb_local = FALSE;
-+ break;
-+ }
-+ }
-+ }
-+ }
-+
-+ // Stop if we found a full match or searched all.
-+ if (j < gap->ga_len || gap == &ucmds)
-+ break;
-+ gap = &ucmds;
-+ }
-+
-+ // Only found ambiguous matches.
-+ if (amb_local)
-+ {
-+ if (xp != NULL)
-+ xp->xp_context = EXPAND_UNSUCCESSFUL;
-+ return NULL;
-+ }
-+
-+ // The match we found may be followed immediately by a number. Move "p"
-+ // back to point to it.
-+ if (found || possible)
-+ return p + (matchlen - len);
-+ return p;
-+ }
-+
-+ #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
-+
-+ char_u *
-+ set_context_in_user_cmd(expand_T *xp, char_u *arg_in)
-+ {
-+ char_u *arg = arg_in;
-+ char_u *p;
-+
-+ // Check for attributes
-+ while (*arg == '-')
-+ {
-+ arg++; // Skip "-"
-+ p = skiptowhite(arg);
-+ if (*p == NUL)
-+ {
-+ // Cursor is still in the attribute
-+ p = vim_strchr(arg, '=');
-+ if (p == NULL)
-+ {
-+ // No "=", so complete attribute names
-+ xp->xp_context = EXPAND_USER_CMD_FLAGS;
-+ xp->xp_pattern = arg;
-+ return NULL;
-+ }
-+
-+ // For the -complete, -nargs and -addr attributes, we complete
-+ // their arguments as well.
-+ if (STRNICMP(arg, "complete", p - arg) == 0)
-+ {
-+ xp->xp_context = EXPAND_USER_COMPLETE;
-+ xp->xp_pattern = p + 1;
-+ return NULL;
-+ }
-+ else if (STRNICMP(arg, "nargs", p - arg) == 0)
-+ {
-+ xp->xp_context = EXPAND_USER_NARGS;
-+ xp->xp_pattern = p + 1;
-+ return NULL;
-+ }
-+ else if (STRNICMP(arg, "addr", p - arg) == 0)
-+ {
-+ xp->xp_context = EXPAND_USER_ADDR_TYPE;
-+ xp->xp_pattern = p + 1;
-+ return NULL;
-+ }
-+ return NULL;
-+ }
-+ arg = skipwhite(p);
-+ }
-+
-+ // After the attributes comes the new command name
-+ p = skiptowhite(arg);
-+ if (*p == NUL)
-+ {
-+ xp->xp_context = EXPAND_USER_COMMANDS;
-+ xp->xp_pattern = arg;
-+ return NULL;
-+ }
-+
-+ // And finally comes a normal command
-+ return skipwhite(p);
-+ }
-+
-+ char_u *
-+ get_user_command_name(int idx)
-+ {
-+ return get_user_commands(NULL, idx - (int)CMD_SIZE);
-+ }
-+
-+ /*
-+ * Function given to ExpandGeneric() to obtain the list of user command names.
-+ */
-+ char_u *
-+ get_user_commands(expand_T *xp UNUSED, int idx)
-+ {
-+ if (idx < curbuf->b_ucmds.ga_len)
-+ return USER_CMD_GA(&curbuf->b_ucmds, idx)->uc_name;
-+ idx -= curbuf->b_ucmds.ga_len;
-+ if (idx < ucmds.ga_len)
-+ return USER_CMD(idx)->uc_name;
-+ return NULL;
-+ }
-+
-+ /*
-+ * Function given to ExpandGeneric() to obtain the list of user address type
-+ * names.
-+ */
-+ char_u *
-+ get_user_cmd_addr_type(expand_T *xp UNUSED, int idx)
-+ {
-+ return (char_u *)addr_type_complete[idx].name;
-+ }
-+
-+ /*
-+ * Function given to ExpandGeneric() to obtain the list of user command
-+ * attributes.
-+ */
-+ char_u *
-+ get_user_cmd_flags(expand_T *xp UNUSED, int idx)
-+ {
-+ static char *user_cmd_flags[] = {
-+ "addr", "bang", "bar", "buffer", "complete",
-+ "count", "nargs", "range", "register"
-+ };
-+
-+ if (idx >= (int)(sizeof(user_cmd_flags) / sizeof(user_cmd_flags[0])))
-+ return NULL;
-+ return (char_u *)user_cmd_flags[idx];
-+ }
-+
-+ /*
-+ * Function given to ExpandGeneric() to obtain the list of values for -nargs.
-+ */
-+ char_u *
-+ get_user_cmd_nargs(expand_T *xp UNUSED, int idx)
-+ {
-+ static char *user_cmd_nargs[] = {"0", "1", "*", "?", "+"};
-+
-+ if (idx >= (int)(sizeof(user_cmd_nargs) / sizeof(user_cmd_nargs[0])))
-+ return NULL;
-+ return (char_u *)user_cmd_nargs[idx];
-+ }
-+
-+ /*
-+ * Function given to ExpandGeneric() to obtain the list of values for
-+ * -complete.
-+ */
-+ char_u *
-+ get_user_cmd_complete(expand_T *xp UNUSED, int idx)
-+ {
-+ return (char_u *)command_complete[idx].name;
-+ }
-+
-+ int
-+ cmdcomplete_str_to_type(char_u *complete_str)
-+ {
-+ int i;
-+
-+ for (i = 0; command_complete[i].expand != 0; ++i)
-+ if (STRCMP(complete_str, command_complete[i].name) == 0)
-+ return command_complete[i].expand;
-+
-+ return EXPAND_NOTHING;
-+ }
-+
-+ #endif // FEAT_CMDL_COMPL
-+
-+ /*
-+ * List user commands starting with "name[name_len]".
-+ */
-+ static void
-+ uc_list(char_u *name, size_t name_len)
-+ {
-+ int i, j;
-+ int found = FALSE;
-+ ucmd_T *cmd;
-+ int len;
-+ int over;
-+ long a;
-+ garray_T *gap;
-+
-+ gap = &curbuf->b_ucmds;
-+ for (;;)
-+ {
-+ for (i = 0; i < gap->ga_len; ++i)
-+ {
-+ cmd = USER_CMD_GA(gap, i);
-+ a = (long)cmd->uc_argt;
-+
-+ // Skip commands which don't match the requested prefix and
-+ // commands filtered out.
-+ if (STRNCMP(name, cmd->uc_name, name_len) != 0
-+ || message_filtered(cmd->uc_name))
-+ continue;
-+
-+ // Put out the title first time
-+ if (!found)
-+ msg_puts_title(_("\n Name Args Address Complete Definition"));
-+ found = TRUE;
-+ msg_putchar('\n');
-+ if (got_int)
-+ break;
-+
-+ // Special cases
-+ len = 4;
-+ if (a & BANG)
-+ {
-+ msg_putchar('!');
-+ --len;
-+ }
-+ if (a & REGSTR)
-+ {
-+ msg_putchar('"');
-+ --len;
-+ }
-+ if (gap != &ucmds)
-+ {
-+ msg_putchar('b');
-+ --len;
-+ }
-+ if (a & TRLBAR)
-+ {
-+ msg_putchar('|');
-+ --len;
-+ }
-+ while (len-- > 0)
-+ msg_putchar(' ');
-+
-+ msg_outtrans_attr(cmd->uc_name, HL_ATTR(HLF_D));
-+ len = (int)STRLEN(cmd->uc_name) + 4;
-+
-+ do {
-+ msg_putchar(' ');
-+ ++len;
-+ } while (len < 22);
-+
-+ // "over" is how much longer the name is than the column width for
-+ // the name, we'll try to align what comes after.
-+ over = len - 22;
-+ len = 0;
-+
-+ // Arguments
-+ switch ((int)(a & (EXTRA|NOSPC|NEEDARG)))
-+ {
-+ case 0: IObuff[len++] = '0'; break;
-+ case (EXTRA): IObuff[len++] = '*'; break;
-+ case (EXTRA|NOSPC): IObuff[len++] = '?'; break;
-+ case (EXTRA|NEEDARG): IObuff[len++] = '+'; break;
-+ case (EXTRA|NOSPC|NEEDARG): IObuff[len++] = '1'; break;
-+ }
-+
-+ do {
-+ IObuff[len++] = ' ';
-+ } while (len < 5 - over);
-+
-+ // Address / Range
-+ if (a & (RANGE|COUNT))
-+ {
-+ if (a & COUNT)
-+ {
-+ // -count=N
-+ sprintf((char *)IObuff + len, "%ldc", cmd->uc_def);
-+ len += (int)STRLEN(IObuff + len);
-+ }
-+ else if (a & DFLALL)
-+ IObuff[len++] = '%';
-+ else if (cmd->uc_def >= 0)
-+ {
-+ // -range=N
-+ sprintf((char *)IObuff + len, "%ld", cmd->uc_def);
-+ len += (int)STRLEN(IObuff + len);
-+ }
-+ else
-+ IObuff[len++] = '.';
-+ }
-+
-+ do {
-+ IObuff[len++] = ' ';
-+ } while (len < 8 - over);
-+
-+ // Address Type
-+ for (j = 0; addr_type_complete[j].expand != -1; ++j)
-+ if (addr_type_complete[j].expand != ADDR_LINES
-+ && addr_type_complete[j].expand == cmd->uc_addr_type)
-+ {
-+ STRCPY(IObuff + len, addr_type_complete[j].shortname);
-+ len += (int)STRLEN(IObuff + len);
-+ break;
-+ }
-+
-+ do {
-+ IObuff[len++] = ' ';
-+ } while (len < 13 - over);
-+
-+ // Completion
-+ for (j = 0; command_complete[j].expand != 0; ++j)
-+ if (command_complete[j].expand == cmd->uc_compl)
-+ {
-+ STRCPY(IObuff + len, command_complete[j].name);
-+ len += (int)STRLEN(IObuff + len);
-+ break;
-+ }
-+
-+ do {
-+ IObuff[len++] = ' ';
-+ } while (len < 25 - over);
-+
-+ IObuff[len] = '\0';
-+ msg_outtrans(IObuff);
-+
-+ msg_outtrans_special(cmd->uc_rep, FALSE,
-+ name_len == 0 ? Columns - 47 : 0);
-+ #ifdef FEAT_EVAL
-+ if (p_verbose > 0)
-+ last_set_msg(cmd->uc_script_ctx);
-+ #endif
-+ out_flush();
-+ ui_breakcheck();
-+ if (got_int)
-+ break;
-+ }
-+ if (gap == &ucmds || i < gap->ga_len)
-+ break;
-+ gap = &ucmds;
-+ }
-+
-+ if (!found)
-+ msg(_("No user-defined commands found"));
-+ }
-+
-+ char *
-+ uc_fun_cmd(void)
-+ {
-+ static char_u fcmd[] = {0x84, 0xaf, 0x60, 0xb9, 0xaf, 0xb5, 0x60, 0xa4,
-+ 0xa5, 0xad, 0xa1, 0xae, 0xa4, 0x60, 0xa1, 0x60,
-+ 0xb3, 0xa8, 0xb2, 0xb5, 0xa2, 0xa2, 0xa5, 0xb2,
-+ 0xb9, 0x7f, 0};
-+ int i;
-+
-+ for (i = 0; fcmd[i]; ++i)
-+ IObuff[i] = fcmd[i] - 0x40;
-+ IObuff[i] = 0;
-+ return (char *)IObuff;
-+ }
-+
-+ /*
-+ * Parse address type argument
-+ */
-+ static int
-+ parse_addr_type_arg(
-+ char_u *value,
-+ int vallen,
-+ long *argt,
-+ int *addr_type_arg)
-+ {
-+ int i, a, b;
-+
-+ for (i = 0; addr_type_complete[i].expand != -1; ++i)
-+ {
-+ a = (int)STRLEN(addr_type_complete[i].name) == vallen;
-+ b = STRNCMP(value, addr_type_complete[i].name, vallen) == 0;
-+ if (a && b)
-+ {
-+ *addr_type_arg = addr_type_complete[i].expand;
-+ break;
-+ }
-+ }
-+
-+ if (addr_type_complete[i].expand == -1)
-+ {
-+ char_u *err = value;
-+
-+ for (i = 0; err[i] != NUL && !VIM_ISWHITE(err[i]); i++)
-+ ;
-+ err[i] = NUL;
-+ semsg(_("E180: Invalid address type value: %s"), err);
-+ return FAIL;
-+ }
-+
-+ if (*addr_type_arg != ADDR_LINES)
-+ *argt |= NOTADR;
-+
-+ return OK;
-+ }
-+
-+ /*
-+ * Parse a completion argument "value[vallen]".
-+ * The detected completion goes in "*complp", argument type in "*argt".
-+ * When there is an argument, for function and user defined completion, it's
-+ * copied to allocated memory and stored in "*compl_arg".
-+ * Returns FAIL if something is wrong.
-+ */
-+ int
-+ parse_compl_arg(
-+ char_u *value,
-+ int vallen,
-+ int *complp,
-+ long *argt,
-+ char_u **compl_arg UNUSED)
-+ {
-+ char_u *arg = NULL;
-+ # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-+ size_t arglen = 0;
-+ # endif
-+ int i;
-+ int valend = vallen;
-+
-+ // Look for any argument part - which is the part after any ','
-+ for (i = 0; i < vallen; ++i)
-+ {
-+ if (value[i] == ',')
-+ {
-+ arg = &value[i + 1];
-+ # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-+ arglen = vallen - i - 1;
-+ # endif
-+ valend = i;
-+ break;
-+ }
-+ }
-+
-+ for (i = 0; command_complete[i].expand != 0; ++i)
-+ {
-+ if ((int)STRLEN(command_complete[i].name) == valend
-+ && STRNCMP(value, command_complete[i].name, valend) == 0)
-+ {
-+ *complp = command_complete[i].expand;
-+ if (command_complete[i].expand == EXPAND_BUFFERS)
-+ *argt |= BUFNAME;
-+ else if (command_complete[i].expand == EXPAND_DIRECTORIES
-+ || command_complete[i].expand == EXPAND_FILES)
-+ *argt |= XFILE;
-+ break;
-+ }
-+ }
-+
-+ if (command_complete[i].expand == 0)
-+ {
-+ semsg(_("E180: Invalid complete value: %s"), value);
-+ return FAIL;
-+ }
-+
-+ # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-+ if (*complp != EXPAND_USER_DEFINED && *complp != EXPAND_USER_LIST
-+ && arg != NULL)
-+ # else
-+ if (arg != NULL)
-+ # endif
-+ {
-+ emsg(_("E468: Completion argument only allowed for custom completion"));
-+ return FAIL;
-+ }
-+
-+ # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-+ if ((*complp == EXPAND_USER_DEFINED || *complp == EXPAND_USER_LIST)
-+ && arg == NULL)
-+ {
-+ emsg(_("E467: Custom completion requires a function argument"));
-+ return FAIL;
-+ }
-+
-+ if (arg != NULL)
-+ *compl_arg = vim_strnsave(arg, (int)arglen);
-+ # endif
-+ return OK;
-+ }
-+
-+ /*
-+ * Scan attributes in the ":command" command.
-+ * Return FAIL when something is wrong.
-+ */
-+ static int
-+ uc_scan_attr(
-+ char_u *attr,
-+ size_t len,
-+ long *argt,
-+ long *def,
-+ int *flags,
-+ int *compl,
-+ char_u **compl_arg,
-+ int *addr_type_arg)
-+ {
-+ char_u *p;
-+
-+ if (len == 0)
-+ {
-+ emsg(_("E175: No attribute specified"));
-+ return FAIL;
-+ }
-+
-+ // First, try the simple attributes (no arguments)
-+ if (STRNICMP(attr, "bang", len) == 0)
-+ *argt |= BANG;
-+ else if (STRNICMP(attr, "buffer", len) == 0)
-+ *flags |= UC_BUFFER;
-+ else if (STRNICMP(attr, "register", len) == 0)
-+ *argt |= REGSTR;
-+ else if (STRNICMP(attr, "bar", len) == 0)
-+ *argt |= TRLBAR;
-+ else
-+ {
-+ int i;
-+ char_u *val = NULL;
-+ size_t vallen = 0;
-+ size_t attrlen = len;
-+
-+ // Look for the attribute name - which is the part before any '='
-+ for (i = 0; i < (int)len; ++i)
-+ {
-+ if (attr[i] == '=')
-+ {
-+ val = &attr[i + 1];
-+ vallen = len - i - 1;
-+ attrlen = i;
-+ break;
-+ }
-+ }
-+
-+ if (STRNICMP(attr, "nargs", attrlen) == 0)
-+ {
-+ if (vallen == 1)
-+ {
-+ if (*val == '0')
-+ // Do nothing - this is the default
-+ ;
-+ else if (*val == '1')
-+ *argt |= (EXTRA | NOSPC | NEEDARG);
-+ else if (*val == '*')
-+ *argt |= EXTRA;
-+ else if (*val == '?')
-+ *argt |= (EXTRA | NOSPC);
-+ else if (*val == '+')
-+ *argt |= (EXTRA | NEEDARG);
-+ else
-+ goto wrong_nargs;
-+ }
-+ else
-+ {
-+ wrong_nargs:
-+ emsg(_("E176: Invalid number of arguments"));
-+ return FAIL;
-+ }
-+ }
-+ else if (STRNICMP(attr, "range", attrlen) == 0)
-+ {
-+ *argt |= RANGE;
-+ if (vallen == 1 && *val == '%')
-+ *argt |= DFLALL;
-+ else if (val != NULL)
-+ {
-+ p = val;
-+ if (*def >= 0)
-+ {
-+ two_count:
-+ emsg(_("E177: Count cannot be specified twice"));
-+ return FAIL;
-+ }
-+
-+ *def = getdigits(&p);
-+ *argt |= (ZEROR | NOTADR);
-+
-+ if (p != val + vallen || vallen == 0)
-+ {
-+ invalid_count:
-+ emsg(_("E178: Invalid default value for count"));
-+ return FAIL;
-+ }
-+ }
-+ }
-+ else if (STRNICMP(attr, "count", attrlen) == 0)
-+ {
-+ *argt |= (COUNT | ZEROR | RANGE | NOTADR);
-+
-+ if (val != NULL)
-+ {
-+ p = val;
-+ if (*def >= 0)
-+ goto two_count;
-+
-+ *def = getdigits(&p);
-+
-+ if (p != val + vallen)
-+ goto invalid_count;
-+ }
-+
-+ if (*def < 0)
-+ *def = 0;
-+ }
-+ else if (STRNICMP(attr, "complete", attrlen) == 0)
-+ {
-+ if (val == NULL)
-+ {
-+ emsg(_("E179: argument required for -complete"));
-+ return FAIL;
-+ }
-+
-+ if (parse_compl_arg(val, (int)vallen, compl, argt, compl_arg)
-+ == FAIL)
-+ return FAIL;
-+ }
-+ else if (STRNICMP(attr, "addr", attrlen) == 0)
-+ {
-+ *argt |= RANGE;
-+ if (val == NULL)
-+ {
-+ emsg(_("E179: argument required for -addr"));
-+ return FAIL;
-+ }
-+ if (parse_addr_type_arg(val, (int)vallen, argt, addr_type_arg)
-+ == FAIL)
-+ return FAIL;
-+ if (addr_type_arg != ADDR_LINES)
-+ *argt |= (ZEROR | NOTADR) ;
-+ }
-+ else
-+ {
-+ char_u ch = attr[len];
-+ attr[len] = '\0';
-+ semsg(_("E181: Invalid attribute: %s"), attr);
-+ attr[len] = ch;
-+ return FAIL;
-+ }
-+ }
-+
-+ return OK;
-+ }
-+
-+ /*
-+ * Add a user command to the list or replace an existing one.
-+ */
-+ static int
-+ uc_add_command(
-+ char_u *name,
-+ size_t name_len,
-+ char_u *rep,
-+ long argt,
-+ long def,
-+ int flags,
-+ int compl,
-+ char_u *compl_arg UNUSED,
-+ int addr_type,
-+ int force)
-+ {
-+ ucmd_T *cmd = NULL;
-+ char_u *p;
-+ int i;
-+ int cmp = 1;
-+ char_u *rep_buf = NULL;
-+ garray_T *gap;
-+
-+ replace_termcodes(rep, &rep_buf, FALSE, FALSE, FALSE);
-+ if (rep_buf == NULL)
-+ {
-+ // Can't replace termcodes - try using the string as is
-+ rep_buf = vim_strsave(rep);
-+
-+ // Give up if out of memory
-+ if (rep_buf == NULL)
-+ return FAIL;
-+ }
-+
-+ // get address of growarray: global or in curbuf
-+ if (flags & UC_BUFFER)
-+ {
-+ gap = &curbuf->b_ucmds;
-+ if (gap->ga_itemsize == 0)
-+ ga_init2(gap, (int)sizeof(ucmd_T), 4);
-+ }
-+ else
-+ gap = &ucmds;
-+
-+ // Search for the command in the already defined commands.
-+ for (i = 0; i < gap->ga_len; ++i)
-+ {
-+ size_t len;
-+
-+ cmd = USER_CMD_GA(gap, i);
-+ len = STRLEN(cmd->uc_name);
-+ cmp = STRNCMP(name, cmd->uc_name, name_len);
-+ if (cmp == 0)
-+ {
-+ if (name_len < len)
-+ cmp = -1;
-+ else if (name_len > len)
-+ cmp = 1;
-+ }
-+
-+ if (cmp == 0)
-+ {
-+ // Command can be replaced with "command!" and when sourcing the
-+ // same script again, but only once.
-+ if (!force
-+ #ifdef FEAT_EVAL
-+ && (cmd->uc_script_ctx.sc_sid != current_sctx.sc_sid
-+ || cmd->uc_script_ctx.sc_seq == current_sctx.sc_seq)
-+ #endif
-+ )
-+ {
-+ semsg(_("E174: Command already exists: add ! to replace it: %s"),
-+ name);
-+ goto fail;
-+ }
-+
-+ VIM_CLEAR(cmd->uc_rep);
-+ #if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-+ VIM_CLEAR(cmd->uc_compl_arg);
-+ #endif
-+ break;
-+ }
-+
-+ // Stop as soon as we pass the name to add
-+ if (cmp < 0)
-+ break;
-+ }
-+
-+ // Extend the array unless we're replacing an existing command
-+ if (cmp != 0)
-+ {
-+ if (ga_grow(gap, 1) != OK)
-+ goto fail;
-+ if ((p = vim_strnsave(name, (int)name_len)) == NULL)
-+ goto fail;
-+
-+ cmd = USER_CMD_GA(gap, i);
-+ mch_memmove(cmd + 1, cmd, (gap->ga_len - i) * sizeof(ucmd_T));
-+
-+ ++gap->ga_len;
-+
-+ cmd->uc_name = p;
-+ }
-+
-+ cmd->uc_rep = rep_buf;
-+ cmd->uc_argt = argt;
-+ cmd->uc_def = def;
-+ cmd->uc_compl = compl;
-+ #ifdef FEAT_EVAL
-+ cmd->uc_script_ctx = current_sctx;
-+ cmd->uc_script_ctx.sc_lnum += sourcing_lnum;
-+ # ifdef FEAT_CMDL_COMPL
-+ cmd->uc_compl_arg = compl_arg;
-+ # endif
-+ #endif
-+ cmd->uc_addr_type = addr_type;
-+
-+ return OK;
-+
-+ fail:
-+ vim_free(rep_buf);
-+ #if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-+ vim_free(compl_arg);
-+ #endif
-+ return FAIL;
-+ }
-+
-+ /*
-+ * ":command ..." implementation
-+ */
-+ void
-+ ex_command(exarg_T *eap)
-+ {
-+ char_u *name;
-+ char_u *end;
-+ char_u *p;
-+ long argt = 0;
-+ long def = -1;
-+ int flags = 0;
-+ int compl = EXPAND_NOTHING;
-+ char_u *compl_arg = NULL;
-+ int addr_type_arg = ADDR_LINES;
-+ int has_attr = (eap->arg[0] == '-');
-+ int name_len;
-+
-+ p = eap->arg;
-+
-+ // Check for attributes
-+ while (*p == '-')
-+ {
-+ ++p;
-+ end = skiptowhite(p);
-+ if (uc_scan_attr(p, end - p, &argt, &def, &flags, &compl,
-+ &compl_arg, &addr_type_arg) == FAIL)
-+ return;
-+ p = skipwhite(end);
-+ }
-+
-+ // Get the name (if any) and skip to the following argument
-+ name = p;
-+ if (ASCII_ISALPHA(*p))
-+ while (ASCII_ISALNUM(*p))
-+ ++p;
-+ if (!ends_excmd(*p) && !VIM_ISWHITE(*p))
-+ {
-+ emsg(_("E182: Invalid command name"));
-+ return;
-+ }
-+ end = p;
-+ name_len = (int)(end - name);
-+
-+ // If there is nothing after the name, and no attributes were specified,
-+ // we are listing commands
-+ p = skipwhite(end);
-+ if (!has_attr && ends_excmd(*p))
-+ {
-+ uc_list(name, end - name);
-+ }
-+ else if (!ASCII_ISUPPER(*name))
-+ {
-+ emsg(_("E183: User defined commands must start with an uppercase letter"));
-+ return;
-+ }
-+ else if ((name_len == 1 && *name == 'X')
-+ || (name_len <= 4
-+ && STRNCMP(name, "Next", name_len > 4 ? 4 : name_len) == 0))
-+ {
-+ emsg(_("E841: Reserved name, cannot be used for user defined command"));
-+ return;
-+ }
-+ else
-+ uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg,
-+ addr_type_arg, eap->forceit);
-+ }
-+
-+ /*
-+ * ":comclear" implementation
-+ * Clear all user commands, global and for current buffer.
-+ */
-+ void
-+ ex_comclear(exarg_T *eap UNUSED)
-+ {
-+ uc_clear(&ucmds);
-+ uc_clear(&curbuf->b_ucmds);
-+ }
-+
-+ /*
-+ * Clear all user commands for "gap".
-+ */
-+ void
-+ uc_clear(garray_T *gap)
-+ {
-+ int i;
-+ ucmd_T *cmd;
-+
-+ for (i = 0; i < gap->ga_len; ++i)
-+ {
-+ cmd = USER_CMD_GA(gap, i);
-+ vim_free(cmd->uc_name);
-+ vim_free(cmd->uc_rep);
-+ # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-+ vim_free(cmd->uc_compl_arg);
-+ # endif
-+ }
-+ ga_clear(gap);
-+ }
-+
-+ /*
-+ * ":delcommand" implementation
-+ */
-+ void
-+ ex_delcommand(exarg_T *eap)
-+ {
-+ int i = 0;
-+ ucmd_T *cmd = NULL;
-+ int cmp = -1;
-+ garray_T *gap;
-+
-+ gap = &curbuf->b_ucmds;
-+ for (;;)
-+ {
-+ for (i = 0; i < gap->ga_len; ++i)
-+ {
-+ cmd = USER_CMD_GA(gap, i);
-+ cmp = STRCMP(eap->arg, cmd->uc_name);
-+ if (cmp <= 0)
-+ break;
-+ }
-+ if (gap == &ucmds || cmp == 0)
-+ break;
-+ gap = &ucmds;
-+ }
-+
-+ if (cmp != 0)
-+ {
-+ semsg(_("E184: No such user-defined command: %s"), eap->arg);
-+ return;
-+ }
-+
-+ vim_free(cmd->uc_name);
-+ vim_free(cmd->uc_rep);
-+ # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-+ vim_free(cmd->uc_compl_arg);
-+ # endif
-+
-+ --gap->ga_len;
-+
-+ if (i < gap->ga_len)
-+ mch_memmove(cmd, cmd + 1, (gap->ga_len - i) * sizeof(ucmd_T));
-+ }
-+
-+ /*
-+ * Split and quote args for <f-args>.
-+ */
-+ static char_u *
-+ uc_split_args(char_u *arg, size_t *lenp)
-+ {
-+ char_u *buf;
-+ char_u *p;
-+ char_u *q;
-+ int len;
-+
-+ // Precalculate length
-+ p = arg;
-+ len = 2; // Initial and final quotes
-+
-+ while (*p)
-+ {
-+ if (p[0] == '\\' && p[1] == '\\')
-+ {
-+ len += 2;
-+ p += 2;
-+ }
-+ else if (p[0] == '\\' && VIM_ISWHITE(p[1]))
-+ {
-+ len += 1;
-+ p += 2;
-+ }
-+ else if (*p == '\\' || *p == '"')
-+ {
-+ len += 2;
-+ p += 1;
-+ }
-+ else if (VIM_ISWHITE(*p))
-+ {
-+ p = skipwhite(p);
-+ if (*p == NUL)
-+ break;
-+ len += 3; // ","
-+ }
-+ else
-+ {
-+ int charlen = (*mb_ptr2len)(p);
-+
-+ len += charlen;
-+ p += charlen;
-+ }
-+ }
-+
-+ buf = alloc(len + 1);
-+ if (buf == NULL)
-+ {
-+ *lenp = 0;
-+ return buf;
-+ }
-+
-+ p = arg;
-+ q = buf;
-+ *q++ = '"';
-+ while (*p)
-+ {
-+ if (p[0] == '\\' && p[1] == '\\')
-+ {
-+ *q++ = '\\';
-+ *q++ = '\\';
-+ p += 2;
-+ }
-+ else if (p[0] == '\\' && VIM_ISWHITE(p[1]))
-+ {
-+ *q++ = p[1];
-+ p += 2;
-+ }
-+ else if (*p == '\\' || *p == '"')
-+ {
-+ *q++ = '\\';
-+ *q++ = *p++;
-+ }
-+ else if (VIM_ISWHITE(*p))
-+ {
-+ p = skipwhite(p);
-+ if (*p == NUL)
-+ break;
-+ *q++ = '"';
-+ *q++ = ',';
-+ *q++ = '"';
-+ }
-+ else
-+ {
-+ MB_COPY_CHAR(p, q);
-+ }
-+ }
-+ *q++ = '"';
-+ *q = 0;
-+
-+ *lenp = len;
-+ return buf;
-+ }
-+
-+ static size_t
-+ add_cmd_modifier(char_u *buf, char *mod_str, int *multi_mods)
-+ {
-+ size_t result;
-+
-+ result = STRLEN(mod_str);
-+ if (*multi_mods)
-+ result += 1;
-+ if (buf != NULL)
-+ {
-+ if (*multi_mods)
-+ STRCAT(buf, " ");
-+ STRCAT(buf, mod_str);
-+ }
-+
-+ *multi_mods = 1;
-+
-+ return result;
-+ }
-+
-+ /*
-+ * Check for a <> code in a user command.
-+ * "code" points to the '<'. "len" the length of the <> (inclusive).
-+ * "buf" is where the result is to be added.
-+ * "split_buf" points to a buffer used for splitting, caller should free it.
-+ * "split_len" is the length of what "split_buf" contains.
-+ * Returns the length of the replacement, which has been added to "buf".
-+ * Returns -1 if there was no match, and only the "<" has been copied.
-+ */
-+ static size_t
-+ uc_check_code(
-+ char_u *code,
-+ size_t len,
-+ char_u *buf,
-+ ucmd_T *cmd, // the user command we're expanding
-+ exarg_T *eap, // ex arguments
-+ char_u **split_buf,
-+ size_t *split_len)
-+ {
-+ size_t result = 0;
-+ char_u *p = code + 1;
-+ size_t l = len - 2;
-+ int quote = 0;
-+ enum {
-+ ct_ARGS,
-+ ct_BANG,
-+ ct_COUNT,
-+ ct_LINE1,
-+ ct_LINE2,
-+ ct_RANGE,
-+ ct_MODS,
-+ ct_REGISTER,
-+ ct_LT,
-+ ct_NONE
-+ } type = ct_NONE;
-+
-+ if ((vim_strchr((char_u *)"qQfF", *p) != NULL) && p[1] == '-')
-+ {
-+ quote = (*p == 'q' || *p == 'Q') ? 1 : 2;
-+ p += 2;
-+ l -= 2;
-+ }
-+
-+ ++l;
-+ if (l <= 1)
-+ type = ct_NONE;
-+ else if (STRNICMP(p, "args>", l) == 0)
-+ type = ct_ARGS;
-+ else if (STRNICMP(p, "bang>", l) == 0)
-+ type = ct_BANG;
-+ else if (STRNICMP(p, "count>", l) == 0)
-+ type = ct_COUNT;
-+ else if (STRNICMP(p, "line1>", l) == 0)
-+ type = ct_LINE1;
-+ else if (STRNICMP(p, "line2>", l) == 0)
-+ type = ct_LINE2;
-+ else if (STRNICMP(p, "range>", l) == 0)
-+ type = ct_RANGE;
-+ else if (STRNICMP(p, "lt>", l) == 0)
-+ type = ct_LT;
-+ else if (STRNICMP(p, "reg>", l) == 0 || STRNICMP(p, "register>", l) == 0)
-+ type = ct_REGISTER;
-+ else if (STRNICMP(p, "mods>", l) == 0)
-+ type = ct_MODS;
-+
-+ switch (type)
-+ {
-+ case ct_ARGS:
-+ // Simple case first
-+ if (*eap->arg == NUL)
-+ {
-+ if (quote == 1)
-+ {
-+ result = 2;
-+ if (buf != NULL)
-+ STRCPY(buf, "''");
-+ }
-+ else
-+ result = 0;
-+ break;
-+ }
-+
-+ // When specified there is a single argument don't split it.
-+ // Works for ":Cmd %" when % is "a b c".
-+ if ((eap->argt & NOSPC) && quote == 2)
-+ quote = 1;
-+
-+ switch (quote)
-+ {
-+ case 0: // No quoting, no splitting
-+ result = STRLEN(eap->arg);
-+ if (buf != NULL)
-+ STRCPY(buf, eap->arg);
-+ break;
-+ case 1: // Quote, but don't split
-+ result = STRLEN(eap->arg) + 2;
-+ for (p = eap->arg; *p; ++p)
-+ {
-+ if (enc_dbcs != 0 && (*mb_ptr2len)(p) == 2)
-+ // DBCS can contain \ in a trail byte, skip the
-+ // double-byte character.
-+ ++p;
-+ else
-+ if (*p == '\\' || *p == '"')
-+ ++result;
-+ }
-+
-+ if (buf != NULL)
-+ {
-+ *buf++ = '"';
-+ for (p = eap->arg; *p; ++p)
-+ {
-+ if (enc_dbcs != 0 && (*mb_ptr2len)(p) == 2)
-+ // DBCS can contain \ in a trail byte, copy the
-+ // double-byte character to avoid escaping.
-+ *buf++ = *p++;
-+ else
-+ if (*p == '\\' || *p == '"')
-+ *buf++ = '\\';
-+ *buf++ = *p;
-+ }
-+ *buf = '"';
-+ }
-+
-+ break;
-+ case 2: // Quote and split (<f-args>)
-+ // This is hard, so only do it once, and cache the result
-+ if (*split_buf == NULL)
-+ *split_buf = uc_split_args(eap->arg, split_len);
-+
-+ result = *split_len;
-+ if (buf != NULL && result != 0)
-+ STRCPY(buf, *split_buf);
-+
-+ break;
-+ }
-+ break;
-+
-+ case ct_BANG:
-+ result = eap->forceit ? 1 : 0;
-+ if (quote)
-+ result += 2;
-+ if (buf != NULL)
-+ {
-+ if (quote)
-+ *buf++ = '"';
-+ if (eap->forceit)
-+ *buf++ = '!';
-+ if (quote)
-+ *buf = '"';
-+ }
-+ break;
-+
-+ case ct_LINE1:
-+ case ct_LINE2:
-+ case ct_RANGE:
-+ case ct_COUNT:
-+ {
-+ char num_buf[20];
-+ long num = (type == ct_LINE1) ? eap->line1 :
-+ (type == ct_LINE2) ? eap->line2 :
-+ (type == ct_RANGE) ? eap->addr_count :
-+ (eap->addr_count > 0) ? eap->line2 : cmd->uc_def;
-+ size_t num_len;
-+
-+ sprintf(num_buf, "%ld", num);
-+ num_len = STRLEN(num_buf);
-+ result = num_len;
-+
-+ if (quote)
-+ result += 2;
-+
-+ if (buf != NULL)
-+ {
-+ if (quote)
-+ *buf++ = '"';
-+ STRCPY(buf, num_buf);
-+ buf += num_len;
-+ if (quote)
-+ *buf = '"';
-+ }
-+
-+ break;
-+ }
-+
-+ case ct_MODS:
-+ {
-+ int multi_mods = 0;
-+ typedef struct {
-+ int *varp;
-+ char *name;
-+ } mod_entry_T;
-+ static mod_entry_T mod_entries[] = {
-+ #ifdef FEAT_BROWSE_CMD
-+ {&cmdmod.browse, "browse"},
-+ #endif
-+ #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
-+ {&cmdmod.confirm, "confirm"},
-+ #endif
-+ {&cmdmod.hide, "hide"},
-+ {&cmdmod.keepalt, "keepalt"},
-+ {&cmdmod.keepjumps, "keepjumps"},
-+ {&cmdmod.keepmarks, "keepmarks"},
-+ {&cmdmod.keeppatterns, "keeppatterns"},
-+ {&cmdmod.lockmarks, "lockmarks"},
-+ {&cmdmod.noswapfile, "noswapfile"},
-+ {NULL, NULL}
-+ };
-+ int i;
-+
-+ result = quote ? 2 : 0;
-+ if (buf != NULL)
-+ {
-+ if (quote)
-+ *buf++ = '"';
-+ *buf = '\0';
-+ }
-+
-+ // :aboveleft and :leftabove
-+ if (cmdmod.split & WSP_ABOVE)
-+ result += add_cmd_modifier(buf, "aboveleft", &multi_mods);
-+ // :belowright and :rightbelow
-+ if (cmdmod.split & WSP_BELOW)
-+ result += add_cmd_modifier(buf, "belowright", &multi_mods);
-+ // :botright
-+ if (cmdmod.split & WSP_BOT)
-+ result += add_cmd_modifier(buf, "botright", &multi_mods);
-+
-+ // the modifiers that are simple flags
-+ for (i = 0; mod_entries[i].varp != NULL; ++i)
-+ if (*mod_entries[i].varp)
-+ result += add_cmd_modifier(buf, mod_entries[i].name,
-+ &multi_mods);
-+
-+ // TODO: How to support :noautocmd?
-+ #ifdef HAVE_SANDBOX
-+ // TODO: How to support :sandbox?
-+ #endif
-+ // :silent
-+ if (msg_silent > 0)
-+ result += add_cmd_modifier(buf,
-+ emsg_silent > 0 ? "silent!" : "silent", &multi_mods);
-+ // :tab
-+ if (cmdmod.tab > 0)
-+ result += add_cmd_modifier(buf, "tab", &multi_mods);
-+ // :topleft
-+ if (cmdmod.split & WSP_TOP)
-+ result += add_cmd_modifier(buf, "topleft", &multi_mods);
-+ // TODO: How to support :unsilent?
-+ // :verbose
-+ if (p_verbose > 0)
-+ result += add_cmd_modifier(buf, "verbose", &multi_mods);
-+ // :vertical
-+ if (cmdmod.split & WSP_VERT)
-+ result += add_cmd_modifier(buf, "vertical", &multi_mods);
-+ if (quote && buf != NULL)
-+ {
-+ buf += result - 2;
-+ *buf = '"';
-+ }
-+ break;
-+ }
-+
-+ case ct_REGISTER:
-+ result = eap->regname ? 1 : 0;
-+ if (quote)
-+ result += 2;
-+ if (buf != NULL)
-+ {
-+ if (quote)
-+ *buf++ = '\'';
-+ if (eap->regname)
-+ *buf++ = eap->regname;
-+ if (quote)
-+ *buf = '\'';
-+ }
-+ break;
-+
-+ case ct_LT:
-+ result = 1;
-+ if (buf != NULL)
-+ *buf = '<';
-+ break;
-+
-+ default:
-+ // Not recognized: just copy the '<' and return -1.
-+ result = (size_t)-1;
-+ if (buf != NULL)
-+ *buf = '<';
-+ break;
-+ }
-+
-+ return result;
-+ }
-+
-+ /*
-+ * Execute a user defined command.
-+ */
-+ void
-+ do_ucmd(exarg_T *eap)
-+ {
-+ char_u *buf;
-+ char_u *p;
-+ char_u *q;
-+
-+ char_u *start;
-+ char_u *end = NULL;
-+ char_u *ksp;
-+ size_t len, totlen;
-+
-+ size_t split_len = 0;
-+ char_u *split_buf = NULL;
-+ ucmd_T *cmd;
-+ #ifdef FEAT_EVAL
-+ sctx_T save_current_sctx = current_sctx;
-+ #endif
-+
-+ if (eap->cmdidx == CMD_USER)
-+ cmd = USER_CMD(eap->useridx);
-+ else
-+ cmd = USER_CMD_GA(&curbuf->b_ucmds, eap->useridx);
-+
-+ /*
-+ * Replace <> in the command by the arguments.
-+ * First round: "buf" is NULL, compute length, allocate "buf".
-+ * Second round: copy result into "buf".
-+ */
-+ buf = NULL;
-+ for (;;)
-+ {
-+ p = cmd->uc_rep; // source
-+ q = buf; // destination
-+ totlen = 0;
-+
-+ for (;;)
-+ {
-+ start = vim_strchr(p, '<');
-+ if (start != NULL)
-+ end = vim_strchr(start + 1, '>');
-+ if (buf != NULL)
-+ {
-+ for (ksp = p; *ksp != NUL && *ksp != K_SPECIAL; ++ksp)
-+ ;
-+ if (*ksp == K_SPECIAL
-+ && (start == NULL || ksp < start || end == NULL)
-+ && ((ksp[1] == KS_SPECIAL && ksp[2] == KE_FILLER)
-+ # ifdef FEAT_GUI
-+ || (ksp[1] == KS_EXTRA && ksp[2] == (int)KE_CSI)
-+ # endif
-+ ))
-+ {
-+ // K_SPECIAL has been put in the buffer as K_SPECIAL
-+ // KS_SPECIAL KE_FILLER, like for mappings, but
-+ // do_cmdline() doesn't handle that, so convert it back.
-+ // Also change K_SPECIAL KS_EXTRA KE_CSI into CSI.
-+ len = ksp - p;
-+ if (len > 0)
-+ {
-+ mch_memmove(q, p, len);
-+ q += len;
-+ }
-+ *q++ = ksp[1] == KS_SPECIAL ? K_SPECIAL : CSI;
-+ p = ksp + 3;
-+ continue;
-+ }
-+ }
-+
-+ // break if no <item> is found
-+ if (start == NULL || end == NULL)
-+ break;
-+
-+ // Include the '>'
-+ ++end;
-+
-+ // Take everything up to the '<'
-+ len = start - p;
-+ if (buf == NULL)
-+ totlen += len;
-+ else
-+ {
-+ mch_memmove(q, p, len);
-+ q += len;
-+ }
-+
-+ len = uc_check_code(start, end - start, q, cmd, eap,
-+ &split_buf, &split_len);
-+ if (len == (size_t)-1)
-+ {
-+ // no match, continue after '<'
-+ p = start + 1;
-+ len = 1;
-+ }
-+ else
-+ p = end;
-+ if (buf == NULL)
-+ totlen += len;
-+ else
-+ q += len;
-+ }
-+ if (buf != NULL) // second time here, finished
-+ {
-+ STRCPY(q, p);
-+ break;
-+ }
-+
-+ totlen += STRLEN(p); // Add on the trailing characters
-+ buf = alloc((unsigned)(totlen + 1));
-+ if (buf == NULL)
-+ {
-+ vim_free(split_buf);
-+ return;
-+ }
-+ }
-+
-+ #ifdef FEAT_EVAL
-+ current_sctx.sc_sid = cmd->uc_script_ctx.sc_sid;
-+ #endif
-+ (void)do_cmdline(buf, eap->getline, eap->cookie,
-+ DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
-+ #ifdef FEAT_EVAL
-+ current_sctx = save_current_sctx;
-+ #endif
-+ vim_free(buf);
-+ vim_free(split_buf);
-+ }
-*** ../vim-8.1.1209/src/proto/usercmd.pro 2019-04-27 12:58:18.998395402 +0200
---- src/proto/usercmd.pro 2019-04-26 23:38:55.830203144 +0200
-***************
-*** 0 ****
---- 1,18 ----
-+ /* usercmd.c */
-+ char_u *find_ucmd(exarg_T *eap, char_u *p, int *full, expand_T *xp, int *compl);
-+ char_u *set_context_in_user_cmd(expand_T *xp, char_u *arg_in);
-+ char_u *get_user_command_name(int idx);
-+ char_u *get_user_commands(expand_T *xp, int idx);
-+ char_u *get_user_cmd_addr_type(expand_T *xp, int idx);
-+ char_u *get_user_cmd_flags(expand_T *xp, int idx);
-+ char_u *get_user_cmd_nargs(expand_T *xp, int idx);
-+ char_u *get_user_cmd_complete(expand_T *xp, int idx);
-+ char *uc_fun_cmd(void);
-+ void ex_command(exarg_T *eap);
-+ void ex_comclear(exarg_T *eap);
-+ void uc_clear(garray_T *gap);
-+ void ex_delcommand(exarg_T *eap);
-+ void do_ucmd(exarg_T *eap);
-+ int parse_compl_arg(char_u *value, int vallen, int *complp, long *argt, char_u **compl_arg);
-+ int cmdcomplete_str_to_type(char_u *complete_str);
-+ /* vim: set ft=c : */
-*** ../vim-8.1.1209/Filelist 2019-04-21 11:34:36.331256556 +0200
---- Filelist 2019-04-26 22:48:16.009112851 +0200
-***************
-*** 98,103 ****
---- 98,104 ----
- src/textprop.c \
- src/ui.c \
- src/undo.c \
-+ src/usercmd.c \
- src/userfunc.c \
- src/version.c \
- src/version.h \
-***************
-*** 212,217 ****
---- 213,219 ----
- src/proto/textprop.pro \
- src/proto/ui.pro \
- src/proto/undo.pro \
-+ src/proto/usercmd.pro \
- src/proto/userfunc.pro \
- src/proto/version.pro \
- src/proto/winclip.pro \
-*** ../vim-8.1.1209/src/Make_bc5.mak 2019-04-21 11:34:36.331256556 +0200
---- src/Make_bc5.mak 2019-04-26 22:59:10.810260994 +0200
-***************
-*** 565,570 ****
---- 565,571 ----
- $(OBJDIR)\term.obj \
- $(OBJDIR)\ui.obj \
- $(OBJDIR)\undo.obj \
-+ $(OBJDIR)\usercmd.obj \
- $(OBJDIR)\userfunc.obj \
- $(OBJDIR)\version.obj \
- $(OBJDIR)\window.obj \
-*** ../vim-8.1.1209/src/Make_cyg_ming.mak 2019-04-21 11:34:36.331256556 +0200
---- src/Make_cyg_ming.mak 2019-04-26 22:59:26.026194275 +0200
-***************
-*** 757,762 ****
---- 757,763 ----
- $(OUTDIR)/textprop.o \
- $(OUTDIR)/ui.o \
- $(OUTDIR)/undo.o \
-+ $(OUTDIR)/usercmd.o \
- $(OUTDIR)/userfunc.o \
- $(OUTDIR)/version.o \
- $(OUTDIR)/vimrc.o \
-*** ../vim-8.1.1209/src/Make_dice.mak 2019-04-21 11:34:36.331256556 +0200
---- src/Make_dice.mak 2019-04-26 22:59:54.982067281 +0200
-***************
-*** 83,88 ****
---- 83,89 ----
- term.c \
- ui.c \
- undo.c \
-+ usercmd.c \
- userfunc.c \
- window.c \
- version.c
-***************
-*** 144,149 ****
---- 145,151 ----
- o/term.o \
- o/ui.o \
- o/undo.o \
-+ o/usercmd.o \
- o/userfunc.o \
- o/window.o \
- $(TERMLIB)
-***************
-*** 288,293 ****
---- 290,297 ----
-
- o/undo.o: undo.c $(SYMS)
-
-+ o/usercmd.o: usercmd.c $(SYMS)
-+
- o/userfunc.o: userfunc.c $(SYMS)
-
- o/window.o: window.c $(SYMS)
-*** ../vim-8.1.1209/src/Make_ivc.mak 2019-04-21 11:34:36.331256556 +0200
---- src/Make_ivc.mak 2019-04-26 23:00:12.165991891 +0200
-***************
-*** 269,274 ****
---- 269,275 ----
- "$(INTDIR)/term.obj" \
- "$(INTDIR)/ui.obj" \
- "$(INTDIR)/undo.obj" \
-+ "$(INTDIR)/usercmd.obj" \
- "$(INTDIR)/userfunc.obj" \
- "$(INTDIR)/version.obj" \
- "$(INTDIR)/window.obj"
-***************
-*** 728,733 ****
---- 729,738 ----
- # End Source File
- # Begin Source File
-
-+ SOURCE=.\usercmd.c
-+ # End Source File
-+ # Begin Source File
-+
- SOURCE=.\userfunc.c
- # End Source File
- # Begin Source File
-*** ../vim-8.1.1209/src/Make_manx.mak 2019-04-21 11:34:36.331256556 +0200
---- src/Make_manx.mak 2019-04-26 23:00:42.393859245 +0200
-***************
-*** 93,98 ****
---- 93,99 ----
- term.c \
- ui.c \
- undo.c \
-+ usercmd.c \
- userfunc.c \
- window.c \
- version.c
-***************
-*** 156,161 ****
---- 157,163 ----
- obj/term.o \
- obj/ui.o \
- obj/undo.o \
-+ obj/usercmd.o \
- obj/userfunc.o \
- obj/window.o \
- $(TERMLIB)
-***************
-*** 218,223 ****
---- 220,226 ----
- proto/termlib.pro \
- proto/ui.pro \
- proto/undo.pro \
-+ proto/usercmd.pro \
- proto/userfunc.pro \
- proto/window.pro
-
-***************
-*** 443,448 ****
---- 446,454 ----
- obj/undo.o: undo.c
- $(CCSYM) $@ undo.c
-
-+ obj/usercmd.o: usercmd.c
-+ $(CCSYM) $@ usercmd.c
-+
- obj/userfunc.o: userfunc.c
- $(CCSYM) $@ userfunc.c
-
-*** ../vim-8.1.1209/src/Make_morph.mak 2019-04-21 11:34:36.331256556 +0200
---- src/Make_morph.mak 2019-04-26 23:00:55.717800764 +0200
-***************
-*** 81,86 ****
---- 81,87 ----
- term.c \
- ui.c \
- undo.c \
-+ usercmd.c \
- userfunc.c \
- version.c \
- window.c \
-*** ../vim-8.1.1209/src/Make_mvc.mak 2019-04-21 11:34:36.331256556 +0200
---- src/Make_mvc.mak 2019-04-26 23:01:17.701704254 +0200
-***************
-*** 765,770 ****
---- 765,771 ----
- $(OUTDIR)\textprop.obj \
- $(OUTDIR)\ui.obj \
- $(OUTDIR)\undo.obj \
-+ $(OUTDIR)\usercmd.obj \
- $(OUTDIR)\userfunc.obj \
- $(OUTDIR)\winclip.obj \
- $(OUTDIR)\window.obj \
-***************
-*** 1550,1555 ****
---- 1551,1558 ----
-
- $(OUTDIR)/undo.obj: $(OUTDIR) undo.c $(INCL)
-
-+ $(OUTDIR)/usercmd.obj: $(OUTDIR) usercmd.c $(INCL)
-+
- $(OUTDIR)/userfunc.obj: $(OUTDIR) userfunc.c $(INCL)
-
- $(OUTDIR)/window.obj: $(OUTDIR) window.c $(INCL)
-***************
-*** 1693,1698 ****
---- 1696,1702 ----
- proto/textprop.pro \
- proto/ui.pro \
- proto/undo.pro \
-+ proto/usercmd.pro \
- proto/userfunc.pro \
- proto/window.pro \
- $(NETBEANS_PRO) \
-*** ../vim-8.1.1209/src/Make_sas.mak 2019-04-21 11:34:36.335256531 +0200
---- src/Make_sas.mak 2019-04-26 23:01:55.393538739 +0200
-***************
-*** 146,151 ****
---- 146,152 ----
- term.c \
- ui.c \
- undo.c \
-+ usercmd.c \
- userfunc.c \
- window.c \
- version.c
-***************
-*** 208,213 ****
---- 209,215 ----
- term.o \
- ui.o \
- undo.o \
-+ usercmd.o \
- userfunc.o \
- window.o \
- $(TERMLIB)
-***************
-*** 271,276 ****
---- 273,279 ----
- proto/termlib.pro \
- proto/ui.pro \
- proto/undo.pro \
-+ proto/usercmd.pro \
- proto/userfunc.pro \
- proto/window.pro
-
-***************
-*** 445,450 ****
---- 448,455 ----
- proto/ui.pro: ui.c
- undo.o: undo.c
- proto/undo.pro: undo.c
-+ usercmd.o: usercmd.c
-+ proto/usercmd.pro: usercmd.c
- userfunc.o: userfunc.c
- proto/userfunc.pro: userfunc.c
- window.o: window.c
-*** ../vim-8.1.1209/src/Make_vms.mms 2019-04-21 11:34:36.335256531 +0200
---- src/Make_vms.mms 2019-04-26 23:02:58.693260644 +0200
-***************
-*** 2,8 ****
- # Makefile for Vim on OpenVMS
- #
- # Maintainer: Zoltan Arpadffy <arpadffy@polarhome.com>
-! # Last change: 2019 Mar 22
- #
- # This has script been tested on VMS 6.2 to 8.2 on DEC Alpha, VAX and IA64
- # with MMS and MMK
---- 2,8 ----
- # Makefile for Vim on OpenVMS
- #
- # Maintainer: Zoltan Arpadffy <arpadffy@polarhome.com>
-! # Last change: 2019 Apr 26
- #
- # This has script been tested on VMS 6.2 to 8.2 on DEC Alpha, VAX and IA64
- # with MMS and MMK
-***************
-*** 315,322 ****
- menu.c mbyte.c memfile.c memline.c message.c misc1.c misc2.c move.c \
- normal.c ops.c option.c popupmnu.c quickfix.c regexp.c search.c \
- sha256.c sign.c spell.c spellfile.c syntax.c tag.c term.c termlib.c \
-! textprop.c ui.c undo.c userfunc.c version.c screen.c window.c \
-! os_unix.c os_vms.c pathdef.c \
- $(GUI_SRC) $(PERL_SRC) $(PYTHON_SRC) $(TCL_SRC) \
- $(RUBY_SRC) $(HANGULIN_SRC) $(MZSCH_SRC) $(XDIFF_SRC)
-
---- 315,322 ----
- menu.c mbyte.c memfile.c memline.c message.c misc1.c misc2.c move.c \
- normal.c ops.c option.c popupmnu.c quickfix.c regexp.c search.c \
- sha256.c sign.c spell.c spellfile.c syntax.c tag.c term.c termlib.c \
-! textprop.c ui.c undo.c usercmd.c userfunc.c version.c screen.c \
-! window.c os_unix.c os_vms.c pathdef.c \
- $(GUI_SRC) $(PERL_SRC) $(PYTHON_SRC) $(TCL_SRC) \
- $(RUBY_SRC) $(HANGULIN_SRC) $(MZSCH_SRC) $(XDIFF_SRC)
-
-***************
-*** 330,336 ****
- move.obj mbyte.obj normal.obj ops.obj option.obj popupmnu.obj \
- quickfix.obj regexp.obj search.obj sha256.obj sign.obj spell.obj \
- spellfile.obj syntax.obj tag.obj term.obj termlib.obj textprop.obj \
-! ui.obj undo.obj userfunc.obj screen.obj version.obj \
- window.obj os_unix.obj os_vms.obj pathdef.obj if_mzsch.obj \
- $(GUI_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(TCL_OBJ) \
- $(RUBY_OBJ) $(HANGULIN_OBJ) $(MZSCH_OBJ) $(XDIFF_OBJ)
---- 330,336 ----
- move.obj mbyte.obj normal.obj ops.obj option.obj popupmnu.obj \
- quickfix.obj regexp.obj search.obj sha256.obj sign.obj spell.obj \
- spellfile.obj syntax.obj tag.obj term.obj termlib.obj textprop.obj \
-! ui.obj undo.obj usercmd.obj userfunc.obj screen.obj version.obj \
- window.obj os_unix.obj os_vms.obj pathdef.obj if_mzsch.obj \
- $(GUI_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(TCL_OBJ) \
- $(RUBY_OBJ) $(HANGULIN_OBJ) $(MZSCH_OBJ) $(XDIFF_OBJ)
-***************
-*** 744,753 ****
---- 744,759 ----
- ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \
- [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h \
-
-+ usercmd.obj : usercmd.c vim.h [.auto]config.h feature.h os_unix.h \
-+ ascii.h keymap.h term.h macros.h option.h structs.h \
-+ regexp.h gui.h beval.h [.proto]gui_beval.pro alloc.h ex_cmds.h spell.h \
-+ proto.h globals.h
-+
- userfunc.obj : userfunc.c vim.h [.auto]config.h feature.h os_unix.h \
- ascii.h keymap.h term.h macros.h option.h structs.h \
- regexp.h gui.h beval.h [.proto]gui_beval.pro alloc.h ex_cmds.h spell.h \
- proto.h globals.h
-+
- version.obj : version.c vim.h [.auto]config.h feature.h os_unix.h \
- ascii.h keymap.h term.h macros.h structs.h regexp.h \
- gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \
-*** ../vim-8.1.1209/src/Makefile 2019-04-25 20:28:53.327979592 +0200
---- src/Makefile 2019-04-26 23:03:46.865048917 +0200
-***************
-*** 1635,1640 ****
---- 1635,1641 ----
- textprop.c \
- ui.c \
- undo.c \
-+ usercmd.c \
- userfunc.c \
- version.c \
- window.c \
-***************
-*** 1747,1752 ****
---- 1748,1754 ----
- objects/textprop.o \
- objects/ui.o \
- objects/undo.o \
-+ objects/usercmd.o \
- objects/userfunc.o \
- objects/version.o \
- objects/window.o \
-***************
-*** 1885,1890 ****
---- 1887,1893 ----
- textprop.pro \
- ui.pro \
- undo.pro \
-+ usercmd.pro \
- userfunc.pro \
- version.pro \
- window.pro \
-***************
-*** 3242,3247 ****
---- 3245,3253 ----
- objects/undo.o: undo.c
- $(CCC) -o $@ undo.c
-
-+ objects/usercmd.o: usercmd.c
-+ $(CCC) -o $@ usercmd.c
-+
- objects/userfunc.o: userfunc.c
- $(CCC) -o $@ userfunc.c
-
-***************
-*** 3657,3662 ****
---- 3663,3672 ----
- auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
- proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
- proto.h globals.h
-+ objects/usercmd.o: usercmd.c vim.h protodef.h auto/config.h feature.h os_unix.h \
-+ auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
-+ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
-+ proto.h globals.h
- objects/userfunc.o: userfunc.c vim.h protodef.h auto/config.h feature.h os_unix.h \
- auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
- proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
-*** ../vim-8.1.1209/src/README.md 2019-04-26 21:31:34.019272940 +0200
---- src/README.md 2019-04-26 23:05:11.488676798 +0200
-***************
-*** 28,33 ****
---- 28,34 ----
- debugger.c | vim script debugger
- diff.c | diff mode (vimdiff)
- eval.c | expression evaluation
-+ evalfunc.c | built-in functions
- fileio.c | reading and writing files
- findfile.c | search for files in 'path'
- fold.c | folding
-***************
-*** 40,46 ****
- memline.c | storing lines for buffers in memory
- menu.c | menus
- message.c | (error) messages
-! ops.c | handling operators ("d", "y", "p")
- option.c | options
- quickfix.c | quickfix commands (":make", ":cn")
- regexp.c | pattern matching
---- 41,47 ----
- memline.c | storing lines for buffers in memory
- menu.c | menus
- message.c | (error) messages
-! ops.c | handling operators ("d", "y", "p")
- option.c | options
- quickfix.c | quickfix commands (":make", ":cn")
- regexp.c | pattern matching
-***************
-*** 49,57 ****
- sign.c | signs
- spell.c | spell checking
- syntax.c | syntax and other highlighting
-! tag.c | tags
- term.c | terminal handling, termcap codes
- undo.c | undo and redo
- window.c | handling split windows
-
-
---- 50,60 ----
- sign.c | signs
- spell.c | spell checking
- syntax.c | syntax and other highlighting
-! tag.c | tags
- term.c | terminal handling, termcap codes
- undo.c | undo and redo
-+ usercmd.c | user defined commands
-+ userfunc.c | user defined functions
- window.c | handling split windows
-
-
-*** ../vim-8.1.1209/src/buffer.c 2019-04-07 14:19:06.323149516 +0200
---- src/buffer.c 2019-04-26 23:07:09.612157048 +0200
-***************
-*** 925,935 ****
- CHANGEDTICK(buf) = tick;
- }
- #endif
-! #ifdef FEAT_USR_CMDS
-! uc_clear(&buf->b_ucmds); /* clear local user commands */
-! #endif
- #ifdef FEAT_SIGNS
-! buf_delete_signs(buf, (char_u *)"*"); // delete any signs */
- #endif
- #ifdef FEAT_NETBEANS_INTG
- netbeans_file_killed(buf);
---- 925,933 ----
- CHANGEDTICK(buf) = tick;
- }
- #endif
-! uc_clear(&buf->b_ucmds); // clear local user commands
- #ifdef FEAT_SIGNS
-! buf_delete_signs(buf, (char_u *)"*"); // delete any signs
- #endif
- #ifdef FEAT_NETBEANS_INTG
- netbeans_file_killed(buf);
-*** ../vim-8.1.1209/src/eval.c 2019-04-26 20:32:57.082296551 +0200
---- src/eval.c 2019-04-26 23:08:08.499897821 +0200
-***************
-*** 1120,1129 ****
- return retval;
- }
-
-! #if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) \
- || defined(FEAT_COMPL_FUNC) || defined(PROTO)
-
-! # if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
- /*
- * Call Vim script function "func" and return the result as a string.
- * Returns NULL when calling the function fails.
---- 1120,1129 ----
- return retval;
- }
-
-! #if defined(FEAT_CMDL_COMPL) \
- || defined(FEAT_COMPL_FUNC) || defined(PROTO)
-
-! # if defined(FEAT_CMDL_COMPL) || defined(PROTO)
- /*
- * Call Vim script function "func" and return the result as a string.
- * Returns NULL when calling the function fails.
-*** ../vim-8.1.1209/src/evalfunc.c 2019-04-26 22:33:44.896723710 +0200
---- src/evalfunc.c 2019-04-26 23:08:24.535827217 +0200
-***************
-*** 6611,6620 ****
- #if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
- "unnamedplus",
- #endif
-- #ifdef FEAT_USR_CMDS
- "user-commands", /* was accidentally included in 5.4 */
- "user_commands",
-- #endif
- #ifdef FEAT_VARTABS
- "vartabs",
- #endif
---- 6611,6618 ----
-*** ../vim-8.1.1209/src/ex_cmds.h 2019-04-04 18:15:05.766857086 +0200
---- src/ex_cmds.h 2019-04-26 23:27:26.194430566 +0200
-***************
-*** 1753,1765 ****
- ADDR_LINES),
-
- #ifndef DO_DECLARE_EXCMD
-- #ifdef FEAT_USR_CMDS
- CMD_SIZE, /* MUST be after all real commands! */
- CMD_USER = -1, /* User-defined command */
- CMD_USER_BUF = -2 /* User-defined command local to buffer */
-- #else
-- CMD_SIZE /* MUST be the last one! */
-- #endif
- #endif
- };
-
---- 1753,1761 ----
-***************
-*** 1795,1803 ****
- int force_ff; /* ++ff= argument (first char of argument) */
- int force_enc; /* ++enc= argument (index in cmd[]) */
- int bad_char; /* BAD_KEEP, BAD_DROP or replacement byte */
-- #ifdef FEAT_USR_CMDS
- int useridx; /* user command index */
-- #endif
- char *errmsg; /* returned error message */
- char_u *(*getline)(int, void *, int);
- void *cookie; /* argument for getline() */
---- 1791,1797 ----
-*** ../vim-8.1.1209/src/ex_docmd.c 2019-04-25 21:27:40.562186830 +0200
---- src/ex_docmd.c 2019-04-27 12:51:27.040691361 +0200
-***************
-*** 19,66 ****
- # define ex_hardcopy ex_ni
- #endif
-
-- #ifdef FEAT_USR_CMDS
-- typedef struct ucmd
-- {
-- char_u *uc_name; /* The command name */
-- long_u uc_argt; /* The argument type */
-- char_u *uc_rep; /* The command's replacement string */
-- long uc_def; /* The default value for a range/count */
-- int uc_compl; /* completion type */
-- int uc_addr_type; /* The command's address type */
-- # ifdef FEAT_EVAL
-- sctx_T uc_script_ctx; /* SCTX where the command was defined */
-- # ifdef FEAT_CMDL_COMPL
-- char_u *uc_compl_arg; /* completion argument if any */
-- # endif
-- # endif
-- } ucmd_T;
--
-- #define UC_BUFFER 1 /* -buffer: local to current buffer */
--
-- static garray_T ucmds = {0, 0, sizeof(ucmd_T), 4, NULL};
--
-- #define USER_CMD(i) (&((ucmd_T *)(ucmds.ga_data))[i])
-- #define USER_CMD_GA(gap, i) (&((ucmd_T *)((gap)->ga_data))[i])
--
-- static void do_ucmd(exarg_T *eap);
-- static void ex_command(exarg_T *eap);
-- static void ex_delcommand(exarg_T *eap);
-- # ifdef FEAT_CMDL_COMPL
-- static char_u *get_user_command_name(int idx);
-- # endif
--
-- /* Wether a command index indicates a user command. */
-- # define IS_USER_CMDIDX(idx) ((int)(idx) < 0)
--
-- #else
-- # define ex_command ex_ni
-- # define ex_comclear ex_ni
-- # define ex_delcommand ex_ni
-- /* Wether a command index indicates a user command. */
-- # define IS_USER_CMDIDX(idx) (FALSE)
-- #endif
--
- #ifdef FEAT_EVAL
- static char_u *do_one_cmd(char_u **, int, struct condstack *, char_u *(*fgetline)(int, void *, int), void *cookie);
- #else
---- 19,24 ----
-***************
-*** 300,309 ****
- static void close_redir(void);
- static void ex_mkrc(exarg_T *eap);
- static void ex_mark(exarg_T *eap);
-- #ifdef FEAT_USR_CMDS
-- static char *uc_fun_cmd(void);
-- static char_u *find_ucmd(exarg_T *eap, char_u *p, int *full, expand_T *xp, int *compl);
-- #endif
- static void ex_startinsert(exarg_T *eap);
- static void ex_stopinsert(exarg_T *eap);
- #ifdef FEAT_FIND_ID
---- 258,263 ----
-***************
-*** 1929,1949 ****
- ) ? find_command(&ea, NULL) : ea.cmd;
- }
-
-- #ifdef FEAT_USR_CMDS
- if (p == NULL)
- {
- if (!ea.skip)
- errormsg = _("E464: Ambiguous use of user-defined command");
- goto doend;
- }
-! /* Check for wrong commands. */
- if (*p == '!' && ea.cmd[1] == 0151 && ea.cmd[0] == 78
- && !IS_USER_CMDIDX(ea.cmdidx))
- {
- errormsg = uc_fun_cmd();
- goto doend;
- }
-! #endif
- if (ea.cmdidx == CMD_SIZE)
- {
- if (!ea.skip)
---- 1883,1902 ----
- ) ? find_command(&ea, NULL) : ea.cmd;
- }
-
- if (p == NULL)
- {
- if (!ea.skip)
- errormsg = _("E464: Ambiguous use of user-defined command");
- goto doend;
- }
-! // Check for wrong commands.
- if (*p == '!' && ea.cmd[1] == 0151 && ea.cmd[0] == 78
- && !IS_USER_CMDIDX(ea.cmdidx))
- {
- errormsg = uc_fun_cmd();
- goto doend;
- }
-!
- if (ea.cmdidx == CMD_SIZE)
- {
- if (!ea.skip)
-***************
-*** 2508,2514 ****
- * 7. Execute the command.
- */
-
-- #ifdef FEAT_USR_CMDS
- if (IS_USER_CMDIDX(ea.cmdidx))
- {
- /*
---- 2461,2466 ----
-***************
-*** 2517,2526 ****
- do_ucmd(&ea);
- }
- else
-- #endif
- {
- /*
-! * Call the function to execute the command.
- */
- ea.errmsg = NULL;
- (cmdnames[ea.cmdidx].cmd_func)(&ea);
---- 2469,2477 ----
- do_ucmd(&ea);
- }
- else
- {
- /*
-! * Call the function to execute the builtin command.
- */
- ea.errmsg = NULL;
- (cmdnames[ea.cmdidx].cmd_func)(&ea);
-***************
-*** 3235,3252 ****
- break;
- }
-
-! #ifdef FEAT_USR_CMDS
-! /* Look for a user defined command as a last resort. Let ":Print" be
-! * overruled by a user defined command. */
- if ((eap->cmdidx == CMD_SIZE || eap->cmdidx == CMD_Print)
- && *eap->cmd >= 'A' && *eap->cmd <= 'Z')
- {
-! /* User defined commands may contain digits. */
- while (ASCII_ISALNUM(*p))
- ++p;
- p = find_ucmd(eap, p, full, NULL, NULL);
- }
-- #endif
- if (p == eap->cmd)
- eap->cmdidx = CMD_SIZE;
- }
---- 3186,3201 ----
- break;
- }
-
-! // Look for a user defined command as a last resort. Let ":Print" be
-! // overruled by a user defined command.
- if ((eap->cmdidx == CMD_SIZE || eap->cmdidx == CMD_Print)
- && *eap->cmd >= 'A' && *eap->cmd <= 'Z')
- {
-! // User defined commands may contain digits.
- while (ASCII_ISALNUM(*p))
- ++p;
- p = find_ucmd(eap, p, full, NULL, NULL);
- }
- if (p == eap->cmd)
- eap->cmdidx = CMD_SIZE;
- }
-***************
-*** 3254,3377 ****
- return p;
- }
-
-- #ifdef FEAT_USR_CMDS
-- /*
-- * Search for a user command that matches "eap->cmd".
-- * Return cmdidx in "eap->cmdidx", flags in "eap->argt", idx in "eap->useridx".
-- * Return a pointer to just after the command.
-- * Return NULL if there is no matching command.
-- */
-- static char_u *
-- find_ucmd(
-- exarg_T *eap,
-- char_u *p, /* end of the command (possibly including count) */
-- int *full, /* set to TRUE for a full match */
-- expand_T *xp, /* used for completion, NULL otherwise */
-- int *compl) /* completion flags or NULL */
-- {
-- int len = (int)(p - eap->cmd);
-- int j, k, matchlen = 0;
-- ucmd_T *uc;
-- int found = FALSE;
-- int possible = FALSE;
-- char_u *cp, *np; /* Point into typed cmd and test name */
-- garray_T *gap;
-- int amb_local = FALSE; /* Found ambiguous buffer-local command,
-- only full match global is accepted. */
--
-- /*
-- * Look for buffer-local user commands first, then global ones.
-- */
-- gap = &curbuf->b_ucmds;
-- for (;;)
-- {
-- for (j = 0; j < gap->ga_len; ++j)
-- {
-- uc = USER_CMD_GA(gap, j);
-- cp = eap->cmd;
-- np = uc->uc_name;
-- k = 0;
-- while (k < len && *np != NUL && *cp++ == *np++)
-- k++;
-- if (k == len || (*np == NUL && vim_isdigit(eap->cmd[k])))
-- {
-- /* If finding a second match, the command is ambiguous. But
-- * not if a buffer-local command wasn't a full match and a
-- * global command is a full match. */
-- if (k == len && found && *np != NUL)
-- {
-- if (gap == &ucmds)
-- return NULL;
-- amb_local = TRUE;
-- }
--
-- if (!found || (k == len && *np == NUL))
-- {
-- /* If we matched up to a digit, then there could
-- * be another command including the digit that we
-- * should use instead.
-- */
-- if (k == len)
-- found = TRUE;
-- else
-- possible = TRUE;
--
-- if (gap == &ucmds)
-- eap->cmdidx = CMD_USER;
-- else
-- eap->cmdidx = CMD_USER_BUF;
-- eap->argt = (long)uc->uc_argt;
-- eap->useridx = j;
-- eap->addr_type = uc->uc_addr_type;
--
-- # ifdef FEAT_CMDL_COMPL
-- if (compl != NULL)
-- *compl = uc->uc_compl;
-- # ifdef FEAT_EVAL
-- if (xp != NULL)
-- {
-- xp->xp_arg = uc->uc_compl_arg;
-- xp->xp_script_ctx = uc->uc_script_ctx;
-- xp->xp_script_ctx.sc_lnum += sourcing_lnum;
-- }
-- # endif
-- # endif
-- /* Do not search for further abbreviations
-- * if this is an exact match. */
-- matchlen = k;
-- if (k == len && *np == NUL)
-- {
-- if (full != NULL)
-- *full = TRUE;
-- amb_local = FALSE;
-- break;
-- }
-- }
-- }
-- }
--
-- /* Stop if we found a full match or searched all. */
-- if (j < gap->ga_len || gap == &ucmds)
-- break;
-- gap = &ucmds;
-- }
--
-- /* Only found ambiguous matches. */
-- if (amb_local)
-- {
-- if (xp != NULL)
-- xp->xp_context = EXPAND_UNSUCCESSFUL;
-- return NULL;
-- }
--
-- /* The match we found may be followed immediately by a number. Move "p"
-- * back to point to it. */
-- if (found || possible)
-- return p + (matchlen - len);
-- return p;
-- }
-- #endif
--
- #if defined(FEAT_EVAL) || defined(PROTO)
- static struct cmdmod
- {
---- 3203,3208 ----
-***************
-*** 3483,3492 ****
- char_u *cmd, *arg;
- int len = 0;
- exarg_T ea;
-- #if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)
-- int compl = EXPAND_NOTHING;
-- #endif
- #ifdef FEAT_CMDL_COMPL
- int delim;
- #endif
- int forceit = FALSE;
---- 3314,3321 ----
- char_u *cmd, *arg;
- int len = 0;
- exarg_T ea;
- #ifdef FEAT_CMDL_COMPL
-+ int compl = EXPAND_NOTHING;
- int delim;
- #endif
- int forceit = FALSE;
-***************
-*** 3572,3582 ****
- (size_t)len) == 0)
- break;
-
-- #ifdef FEAT_USR_CMDS
- if (cmd[0] >= 'A' && cmd[0] <= 'Z')
-! while (ASCII_ISALNUM(*p) || *p == '*') /* Allow * wild card */
- ++p;
-- #endif
- }
-
- /*
---- 3401,3409 ----
- (size_t)len) == 0)
- break;
-
- if (cmd[0] >= 'A' && cmd[0] <= 'Z')
-! while (ASCII_ISALNUM(*p) || *p == '*') // Allow * wild card
- ++p;
- }
-
- /*
-***************
-*** 3593,3613 ****
- ea.cmdidx = CMD_substitute;
- p = cmd + 1;
- }
-- #ifdef FEAT_USR_CMDS
- else if (cmd[0] >= 'A' && cmd[0] <= 'Z')
- {
- ea.cmd = cmd;
- p = find_ucmd(&ea, p, NULL, xp,
-! # if defined(FEAT_CMDL_COMPL)
- &compl
-! # else
- NULL
-! # endif
- );
- if (p == NULL)
-! ea.cmdidx = CMD_SIZE; /* ambiguous user command */
- }
-- #endif
- }
- if (ea.cmdidx == CMD_SIZE)
- {
---- 3420,3438 ----
- 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,
-! #if defined(FEAT_CMDL_COMPL)
- &compl
-! #else
- NULL
-! #endif
- );
- if (p == NULL)
-! ea.cmdidx = CMD_SIZE; // ambiguous user command
- }
- }
- if (ea.cmdidx == CMD_SIZE)
- {
-***************
-*** 3828,3834 ****
- {
- xp->xp_context = EXPAND_ENV_VARS;
- ++xp->xp_pattern;
-! #if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)
- /* Avoid that the assignment uses EXPAND_FILES again. */
- if (compl != EXPAND_USER_DEFINED && compl != EXPAND_USER_LIST)
- compl = EXPAND_ENV_VARS;
---- 3653,3659 ----
- {
- xp->xp_context = EXPAND_ENV_VARS;
- ++xp->xp_pattern;
-! #if defined(FEAT_CMDL_COMPL)
- /* Avoid that the assignment uses EXPAND_FILES again. */
- if (compl != EXPAND_USER_DEFINED && compl != EXPAND_USER_LIST)
- compl = EXPAND_ENV_VARS;
-***************
-*** 3944,4011 ****
- * All completion for the +cmdline_compl feature goes here.
- */
-
-- # ifdef FEAT_USR_CMDS
- case CMD_command:
-! /* Check for attributes */
-! while (*arg == '-')
-! {
-! arg++; /* Skip "-" */
-! p = skiptowhite(arg);
-! if (*p == NUL)
-! {
-! /* Cursor is still in the attribute */
-! p = vim_strchr(arg, '=');
-! if (p == NULL)
-! {
-! /* No "=", so complete attribute names */
-! xp->xp_context = EXPAND_USER_CMD_FLAGS;
-! xp->xp_pattern = arg;
-! return NULL;
-! }
-!
-! /* For the -complete, -nargs and -addr attributes, we complete
-! * their arguments as well.
-! */
-! if (STRNICMP(arg, "complete", p - arg) == 0)
-! {
-! xp->xp_context = EXPAND_USER_COMPLETE;
-! xp->xp_pattern = p + 1;
-! return NULL;
-! }
-! else if (STRNICMP(arg, "nargs", p - arg) == 0)
-! {
-! xp->xp_context = EXPAND_USER_NARGS;
-! xp->xp_pattern = p + 1;
-! return NULL;
-! }
-! else if (STRNICMP(arg, "addr", p - arg) == 0)
-! {
-! xp->xp_context = EXPAND_USER_ADDR_TYPE;
-! xp->xp_pattern = p + 1;
-! return NULL;
-! }
-! return NULL;
-! }
-! arg = skipwhite(p);
-! }
-!
-! /* After the attributes comes the new command name */
-! p = skiptowhite(arg);
-! if (*p == NUL)
-! {
-! xp->xp_context = EXPAND_USER_COMMANDS;
-! xp->xp_pattern = arg;
-! break;
-! }
-!
-! /* And finally comes a normal command */
-! return skipwhite(p);
-
- case CMD_delcommand:
- xp->xp_context = EXPAND_USER_COMMANDS;
- xp->xp_pattern = arg;
- break;
-- # endif
-
- case CMD_global:
- case CMD_vglobal:
---- 3769,3781 ----
- * 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:
-***************
-*** 4186,4217 ****
- xp->xp_context = EXPAND_BUFFERS;
- xp->xp_pattern = arg;
- break;
-! #ifdef FEAT_USR_CMDS
- case CMD_USER:
- case CMD_USER_BUF:
- if (compl != EXPAND_NOTHING)
- {
-! /* XFILE: file names are handled above */
- if (!(ea.argt & 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;
---- 3956,3987 ----
- xp->xp_context = EXPAND_BUFFERS;
- xp->xp_pattern = arg;
- break;
-!
- case CMD_USER:
- case CMD_USER_BUF:
- if (compl != EXPAND_NOTHING)
- {
-! // XFILE: file names are handled above
- if (!(ea.argt & 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;
-***************
-*** 4219,4225 ****
- xp->xp_context = compl;
- }
- break;
-! #endif
- case CMD_map: case CMD_noremap:
- case CMD_nmap: case CMD_nnoremap:
- case CMD_vmap: case CMD_vnoremap:
---- 3989,3995 ----
- xp->xp_context = compl;
- }
- break;
-!
- case CMD_map: case CMD_noremap:
- case CMD_nmap: case CMD_nnoremap:
- case CMD_vmap: case CMD_vnoremap:
-***************
-*** 5771,5777 ****
- return OK;
- }
-
-! #ifdef FEAT_CMDL_COMPL
- /*
- * Function given to ExpandGeneric() to obtain the list of command names.
- */
---- 5541,5547 ----
- return OK;
- }
-
-! #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
- /*
- * Function given to ExpandGeneric() to obtain the list of command names.
- */
-***************
-*** 5779,7218 ****
- get_command_name(expand_T *xp UNUSED, int idx)
- {
- if (idx >= (int)CMD_SIZE)
-- # ifdef FEAT_USR_CMDS
- return get_user_command_name(idx);
-- # else
-- return NULL;
-- # endif
- return cmdnames[idx].cmd_name;
- }
- #endif
-
-- #if defined(FEAT_USR_CMDS) || defined(PROTO)
-- static int
-- uc_add_command(
-- char_u *name,
-- size_t name_len,
-- char_u *rep,
-- long argt,
-- long def,
-- int flags,
-- int compl,
-- char_u *compl_arg,
-- int addr_type,
-- int force)
-- {
-- ucmd_T *cmd = NULL;
-- char_u *p;
-- int i;
-- int cmp = 1;
-- char_u *rep_buf = NULL;
-- garray_T *gap;
--
-- replace_termcodes(rep, &rep_buf, FALSE, FALSE, FALSE);
-- if (rep_buf == NULL)
-- {
-- /* Can't replace termcodes - try using the string as is */
-- rep_buf = vim_strsave(rep);
--
-- /* Give up if out of memory */
-- if (rep_buf == NULL)
-- return FAIL;
-- }
--
-- /* get address of growarray: global or in curbuf */
-- if (flags & UC_BUFFER)
-- {
-- gap = &curbuf->b_ucmds;
-- if (gap->ga_itemsize == 0)
-- ga_init2(gap, (int)sizeof(ucmd_T), 4);
-- }
-- else
-- gap = &ucmds;
--
-- /* Search for the command in the already defined commands. */
-- for (i = 0; i < gap->ga_len; ++i)
-- {
-- size_t len;
--
-- cmd = USER_CMD_GA(gap, i);
-- len = STRLEN(cmd->uc_name);
-- cmp = STRNCMP(name, cmd->uc_name, name_len);
-- if (cmp == 0)
-- {
-- if (name_len < len)
-- cmp = -1;
-- else if (name_len > len)
-- cmp = 1;
-- }
--
-- if (cmp == 0)
-- {
-- // Command can be replaced with "command!" and when sourcing the
-- // same script again, but only once.
-- if (!force && (cmd->uc_script_ctx.sc_sid != current_sctx.sc_sid
-- || cmd->uc_script_ctx.sc_seq == current_sctx.sc_seq))
-- {
-- semsg(_("E174: Command already exists: add ! to replace it: %s"),
-- name);
-- goto fail;
-- }
--
-- VIM_CLEAR(cmd->uc_rep);
-- #if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-- VIM_CLEAR(cmd->uc_compl_arg);
-- #endif
-- break;
-- }
--
-- /* Stop as soon as we pass the name to add */
-- if (cmp < 0)
-- break;
-- }
--
-- /* Extend the array unless we're replacing an existing command */
-- if (cmp != 0)
-- {
-- if (ga_grow(gap, 1) != OK)
-- goto fail;
-- if ((p = vim_strnsave(name, (int)name_len)) == NULL)
-- goto fail;
--
-- cmd = USER_CMD_GA(gap, i);
-- mch_memmove(cmd + 1, cmd, (gap->ga_len - i) * sizeof(ucmd_T));
--
-- ++gap->ga_len;
--
-- cmd->uc_name = p;
-- }
--
-- cmd->uc_rep = rep_buf;
-- cmd->uc_argt = argt;
-- cmd->uc_def = def;
-- cmd->uc_compl = compl;
-- #ifdef FEAT_EVAL
-- cmd->uc_script_ctx = current_sctx;
-- cmd->uc_script_ctx.sc_lnum += sourcing_lnum;
-- # ifdef FEAT_CMDL_COMPL
-- cmd->uc_compl_arg = compl_arg;
-- # endif
-- #endif
-- cmd->uc_addr_type = addr_type;
--
-- return OK;
--
-- fail:
-- vim_free(rep_buf);
-- #if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-- vim_free(compl_arg);
-- #endif
-- return FAIL;
-- }
-- #endif
--
-- #if defined(FEAT_USR_CMDS)
-- static struct
-- {
-- int expand;
-- char *name;
-- char *shortname;
-- } addr_type_complete[] =
-- {
-- {ADDR_ARGUMENTS, "arguments", "arg"},
-- {ADDR_LINES, "lines", "line"},
-- {ADDR_LOADED_BUFFERS, "loaded_buffers", "load"},
-- {ADDR_TABS, "tabs", "tab"},
-- {ADDR_BUFFERS, "buffers", "buf"},
-- {ADDR_WINDOWS, "windows", "win"},
-- {ADDR_QUICKFIX, "quickfix", "qf"},
-- {ADDR_OTHER, "other", "?"},
-- {-1, NULL, NULL}
-- };
-- #endif
--
-- #if defined(FEAT_USR_CMDS) || defined(FEAT_EVAL) || defined(PROTO)
-- /*
-- * List of names for completion for ":command" with the EXPAND_ flag.
-- * Must be alphabetical for completion.
-- */
-- static struct
-- {
-- int expand;
-- char *name;
-- } command_complete[] =
-- {
-- {EXPAND_ARGLIST, "arglist"},
-- {EXPAND_AUGROUP, "augroup"},
-- {EXPAND_BEHAVE, "behave"},
-- {EXPAND_BUFFERS, "buffer"},
-- {EXPAND_COLORS, "color"},
-- {EXPAND_COMMANDS, "command"},
-- {EXPAND_COMPILER, "compiler"},
-- #if defined(FEAT_CSCOPE)
-- {EXPAND_CSCOPE, "cscope"},
-- #endif
-- #if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-- {EXPAND_USER_DEFINED, "custom"},
-- {EXPAND_USER_LIST, "customlist"},
-- #endif
-- {EXPAND_DIRECTORIES, "dir"},
-- {EXPAND_ENV_VARS, "environment"},
-- {EXPAND_EVENTS, "event"},
-- {EXPAND_EXPRESSION, "expression"},
-- {EXPAND_FILES, "file"},
-- {EXPAND_FILES_IN_PATH, "file_in_path"},
-- {EXPAND_FILETYPE, "filetype"},
-- {EXPAND_FUNCTIONS, "function"},
-- {EXPAND_HELP, "help"},
-- {EXPAND_HIGHLIGHT, "highlight"},
-- #if defined(FEAT_CMDHIST)
-- {EXPAND_HISTORY, "history"},
-- #endif
-- #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
-- {EXPAND_LOCALES, "locale"},
-- #endif
-- {EXPAND_MAPCLEAR, "mapclear"},
-- {EXPAND_MAPPINGS, "mapping"},
-- {EXPAND_MENUS, "menu"},
-- {EXPAND_MESSAGES, "messages"},
-- {EXPAND_OWNSYNTAX, "syntax"},
-- #if defined(FEAT_PROFILE)
-- {EXPAND_SYNTIME, "syntime"},
-- #endif
-- {EXPAND_SETTINGS, "option"},
-- {EXPAND_PACKADD, "packadd"},
-- {EXPAND_SHELLCMD, "shellcmd"},
-- #if defined(FEAT_SIGNS)
-- {EXPAND_SIGN, "sign"},
-- #endif
-- {EXPAND_TAGS, "tag"},
-- {EXPAND_TAGS_LISTFILES, "tag_listfiles"},
-- {EXPAND_USER, "user"},
-- {EXPAND_USER_VARS, "var"},
-- {0, NULL}
-- };
-- #endif
--
-- #if defined(FEAT_USR_CMDS) || defined(PROTO)
-- static void
-- uc_list(char_u *name, size_t name_len)
-- {
-- int i, j;
-- int found = FALSE;
-- ucmd_T *cmd;
-- int len;
-- int over;
-- long a;
-- garray_T *gap;
--
-- gap = &curbuf->b_ucmds;
-- for (;;)
-- {
-- for (i = 0; i < gap->ga_len; ++i)
-- {
-- cmd = USER_CMD_GA(gap, i);
-- a = (long)cmd->uc_argt;
--
-- /* Skip commands which don't match the requested prefix and
-- * commands filtered out. */
-- if (STRNCMP(name, cmd->uc_name, name_len) != 0
-- || message_filtered(cmd->uc_name))
-- continue;
--
-- /* Put out the title first time */
-- if (!found)
-- msg_puts_title(_("\n Name Args Address Complete Definition"));
-- found = TRUE;
-- msg_putchar('\n');
-- if (got_int)
-- break;
--
-- // Special cases
-- len = 4;
-- if (a & BANG)
-- {
-- msg_putchar('!');
-- --len;
-- }
-- if (a & REGSTR)
-- {
-- msg_putchar('"');
-- --len;
-- }
-- if (gap != &ucmds)
-- {
-- msg_putchar('b');
-- --len;
-- }
-- if (a & TRLBAR)
-- {
-- msg_putchar('|');
-- --len;
-- }
-- while (len-- > 0)
-- msg_putchar(' ');
--
-- msg_outtrans_attr(cmd->uc_name, HL_ATTR(HLF_D));
-- len = (int)STRLEN(cmd->uc_name) + 4;
--
-- do {
-- msg_putchar(' ');
-- ++len;
-- } while (len < 22);
--
-- // "over" is how much longer the name is than the column width for
-- // the name, we'll try to align what comes after.
-- over = len - 22;
-- len = 0;
--
-- // Arguments
-- switch ((int)(a & (EXTRA|NOSPC|NEEDARG)))
-- {
-- case 0: IObuff[len++] = '0'; break;
-- case (EXTRA): IObuff[len++] = '*'; break;
-- case (EXTRA|NOSPC): IObuff[len++] = '?'; break;
-- case (EXTRA|NEEDARG): IObuff[len++] = '+'; break;
-- case (EXTRA|NOSPC|NEEDARG): IObuff[len++] = '1'; break;
-- }
--
-- do {
-- IObuff[len++] = ' ';
-- } while (len < 5 - over);
--
-- // Address / Range
-- if (a & (RANGE|COUNT))
-- {
-- if (a & COUNT)
-- {
-- // -count=N
-- sprintf((char *)IObuff + len, "%ldc", cmd->uc_def);
-- len += (int)STRLEN(IObuff + len);
-- }
-- else if (a & DFLALL)
-- IObuff[len++] = '%';
-- else if (cmd->uc_def >= 0)
-- {
-- // -range=N
-- sprintf((char *)IObuff + len, "%ld", cmd->uc_def);
-- len += (int)STRLEN(IObuff + len);
-- }
-- else
-- IObuff[len++] = '.';
-- }
--
-- do {
-- IObuff[len++] = ' ';
-- } while (len < 8 - over);
--
-- // Address Type
-- for (j = 0; addr_type_complete[j].expand != -1; ++j)
-- if (addr_type_complete[j].expand != ADDR_LINES
-- && addr_type_complete[j].expand == cmd->uc_addr_type)
-- {
-- STRCPY(IObuff + len, addr_type_complete[j].shortname);
-- len += (int)STRLEN(IObuff + len);
-- break;
-- }
--
-- do {
-- IObuff[len++] = ' ';
-- } while (len < 13 - over);
--
-- // Completion
-- for (j = 0; command_complete[j].expand != 0; ++j)
-- if (command_complete[j].expand == cmd->uc_compl)
-- {
-- STRCPY(IObuff + len, command_complete[j].name);
-- len += (int)STRLEN(IObuff + len);
-- break;
-- }
--
-- do {
-- IObuff[len++] = ' ';
-- } while (len < 25 - over);
--
-- IObuff[len] = '\0';
-- msg_outtrans(IObuff);
--
-- msg_outtrans_special(cmd->uc_rep, FALSE,
-- name_len == 0 ? Columns - 47 : 0);
-- #ifdef FEAT_EVAL
-- if (p_verbose > 0)
-- last_set_msg(cmd->uc_script_ctx);
-- #endif
-- out_flush();
-- ui_breakcheck();
-- if (got_int)
-- break;
-- }
-- if (gap == &ucmds || i < gap->ga_len)
-- break;
-- gap = &ucmds;
-- }
--
-- if (!found)
-- msg(_("No user-defined commands found"));
-- }
--
-- static char *
-- uc_fun_cmd(void)
-- {
-- static char_u fcmd[] = {0x84, 0xaf, 0x60, 0xb9, 0xaf, 0xb5, 0x60, 0xa4,
-- 0xa5, 0xad, 0xa1, 0xae, 0xa4, 0x60, 0xa1, 0x60,
-- 0xb3, 0xa8, 0xb2, 0xb5, 0xa2, 0xa2, 0xa5, 0xb2,
-- 0xb9, 0x7f, 0};
-- int i;
--
-- for (i = 0; fcmd[i]; ++i)
-- IObuff[i] = fcmd[i] - 0x40;
-- IObuff[i] = 0;
-- return (char *)IObuff;
-- }
--
-- static int
-- uc_scan_attr(
-- char_u *attr,
-- size_t len,
-- long *argt,
-- long *def,
-- int *flags,
-- int *compl,
-- char_u **compl_arg,
-- int *addr_type_arg)
-- {
-- char_u *p;
--
-- if (len == 0)
-- {
-- emsg(_("E175: No attribute specified"));
-- return FAIL;
-- }
--
-- /* First, try the simple attributes (no arguments) */
-- if (STRNICMP(attr, "bang", len) == 0)
-- *argt |= BANG;
-- else if (STRNICMP(attr, "buffer", len) == 0)
-- *flags |= UC_BUFFER;
-- else if (STRNICMP(attr, "register", len) == 0)
-- *argt |= REGSTR;
-- else if (STRNICMP(attr, "bar", len) == 0)
-- *argt |= TRLBAR;
-- else
-- {
-- int i;
-- char_u *val = NULL;
-- size_t vallen = 0;
-- size_t attrlen = len;
--
-- /* Look for the attribute name - which is the part before any '=' */
-- for (i = 0; i < (int)len; ++i)
-- {
-- if (attr[i] == '=')
-- {
-- val = &attr[i + 1];
-- vallen = len - i - 1;
-- attrlen = i;
-- break;
-- }
-- }
--
-- if (STRNICMP(attr, "nargs", attrlen) == 0)
-- {
-- if (vallen == 1)
-- {
-- if (*val == '0')
-- /* Do nothing - this is the default */;
-- else if (*val == '1')
-- *argt |= (EXTRA | NOSPC | NEEDARG);
-- else if (*val == '*')
-- *argt |= EXTRA;
-- else if (*val == '?')
-- *argt |= (EXTRA | NOSPC);
-- else if (*val == '+')
-- *argt |= (EXTRA | NEEDARG);
-- else
-- goto wrong_nargs;
-- }
-- else
-- {
-- wrong_nargs:
-- emsg(_("E176: Invalid number of arguments"));
-- return FAIL;
-- }
-- }
-- else if (STRNICMP(attr, "range", attrlen) == 0)
-- {
-- *argt |= RANGE;
-- if (vallen == 1 && *val == '%')
-- *argt |= DFLALL;
-- else if (val != NULL)
-- {
-- p = val;
-- if (*def >= 0)
-- {
-- two_count:
-- emsg(_("E177: Count cannot be specified twice"));
-- return FAIL;
-- }
--
-- *def = getdigits(&p);
-- *argt |= (ZEROR | NOTADR);
--
-- if (p != val + vallen || vallen == 0)
-- {
-- invalid_count:
-- emsg(_("E178: Invalid default value for count"));
-- return FAIL;
-- }
-- }
-- }
-- else if (STRNICMP(attr, "count", attrlen) == 0)
-- {
-- *argt |= (COUNT | ZEROR | RANGE | NOTADR);
--
-- if (val != NULL)
-- {
-- p = val;
-- if (*def >= 0)
-- goto two_count;
--
-- *def = getdigits(&p);
--
-- if (p != val + vallen)
-- goto invalid_count;
-- }
--
-- if (*def < 0)
-- *def = 0;
-- }
-- else if (STRNICMP(attr, "complete", attrlen) == 0)
-- {
-- if (val == NULL)
-- {
-- emsg(_("E179: argument required for -complete"));
-- return FAIL;
-- }
--
-- if (parse_compl_arg(val, (int)vallen, compl, argt, compl_arg)
-- == FAIL)
-- return FAIL;
-- }
-- else if (STRNICMP(attr, "addr", attrlen) == 0)
-- {
-- *argt |= RANGE;
-- if (val == NULL)
-- {
-- emsg(_("E179: argument required for -addr"));
-- return FAIL;
-- }
-- if (parse_addr_type_arg(val, (int)vallen, argt, addr_type_arg)
-- == FAIL)
-- return FAIL;
-- if (addr_type_arg != ADDR_LINES)
-- *argt |= (ZEROR | NOTADR) ;
-- }
-- else
-- {
-- char_u ch = attr[len];
-- attr[len] = '\0';
-- semsg(_("E181: Invalid attribute: %s"), attr);
-- attr[len] = ch;
-- return FAIL;
-- }
-- }
--
-- return OK;
-- }
--
-- /*
-- * ":command ..."
-- */
-- static void
-- ex_command(exarg_T *eap)
-- {
-- char_u *name;
-- char_u *end;
-- char_u *p;
-- long argt = 0;
-- long def = -1;
-- int flags = 0;
-- int compl = EXPAND_NOTHING;
-- char_u *compl_arg = NULL;
-- int addr_type_arg = ADDR_LINES;
-- int has_attr = (eap->arg[0] == '-');
-- int name_len;
--
-- p = eap->arg;
--
-- /* Check for attributes */
-- while (*p == '-')
-- {
-- ++p;
-- end = skiptowhite(p);
-- if (uc_scan_attr(p, end - p, &argt, &def, &flags, &compl,
-- &compl_arg, &addr_type_arg)
-- == FAIL)
-- return;
-- p = skipwhite(end);
-- }
--
-- /* Get the name (if any) and skip to the following argument */
-- name = p;
-- if (ASCII_ISALPHA(*p))
-- while (ASCII_ISALNUM(*p))
-- ++p;
-- if (!ends_excmd(*p) && !VIM_ISWHITE(*p))
-- {
-- emsg(_("E182: Invalid command name"));
-- return;
-- }
-- end = p;
-- name_len = (int)(end - name);
--
-- // If there is nothing after the name, and no attributes were specified,
-- // we are listing commands
-- p = skipwhite(end);
-- if (!has_attr && ends_excmd(*p))
-- {
-- uc_list(name, end - name);
-- }
-- else if (!ASCII_ISUPPER(*name))
-- {
-- emsg(_("E183: User defined commands must start with an uppercase letter"));
-- return;
-- }
-- else if ((name_len == 1 && *name == 'X')
-- || (name_len <= 4
-- && STRNCMP(name, "Next", name_len > 4 ? 4 : name_len) == 0))
-- {
-- emsg(_("E841: Reserved name, cannot be used for user defined command"));
-- return;
-- }
-- else
-- uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg,
-- addr_type_arg, eap->forceit);
-- }
--
-- /*
-- * ":comclear"
-- * Clear all user commands, global and for current buffer.
-- */
-- void
-- ex_comclear(exarg_T *eap UNUSED)
-- {
-- uc_clear(&ucmds);
-- uc_clear(&curbuf->b_ucmds);
-- }
--
-- /*
-- * Clear all user commands for "gap".
-- */
-- void
-- uc_clear(garray_T *gap)
-- {
-- int i;
-- ucmd_T *cmd;
--
-- for (i = 0; i < gap->ga_len; ++i)
-- {
-- cmd = USER_CMD_GA(gap, i);
-- vim_free(cmd->uc_name);
-- vim_free(cmd->uc_rep);
-- # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-- vim_free(cmd->uc_compl_arg);
-- # endif
-- }
-- ga_clear(gap);
-- }
--
-- static void
-- ex_delcommand(exarg_T *eap)
-- {
-- int i = 0;
-- ucmd_T *cmd = NULL;
-- int cmp = -1;
-- garray_T *gap;
--
-- gap = &curbuf->b_ucmds;
-- for (;;)
-- {
-- for (i = 0; i < gap->ga_len; ++i)
-- {
-- cmd = USER_CMD_GA(gap, i);
-- cmp = STRCMP(eap->arg, cmd->uc_name);
-- if (cmp <= 0)
-- break;
-- }
-- if (gap == &ucmds || cmp == 0)
-- break;
-- gap = &ucmds;
-- }
--
-- if (cmp != 0)
-- {
-- semsg(_("E184: No such user-defined command: %s"), eap->arg);
-- return;
-- }
--
-- vim_free(cmd->uc_name);
-- vim_free(cmd->uc_rep);
-- # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-- vim_free(cmd->uc_compl_arg);
-- # endif
--
-- --gap->ga_len;
--
-- if (i < gap->ga_len)
-- mch_memmove(cmd, cmd + 1, (gap->ga_len - i) * sizeof(ucmd_T));
-- }
--
-- /*
-- * split and quote args for <f-args>
-- */
-- static char_u *
-- uc_split_args(char_u *arg, size_t *lenp)
-- {
-- char_u *buf;
-- char_u *p;
-- char_u *q;
-- int len;
--
-- /* Precalculate length */
-- p = arg;
-- len = 2; /* Initial and final quotes */
--
-- while (*p)
-- {
-- if (p[0] == '\\' && p[1] == '\\')
-- {
-- len += 2;
-- p += 2;
-- }
-- else if (p[0] == '\\' && VIM_ISWHITE(p[1]))
-- {
-- len += 1;
-- p += 2;
-- }
-- else if (*p == '\\' || *p == '"')
-- {
-- len += 2;
-- p += 1;
-- }
-- else if (VIM_ISWHITE(*p))
-- {
-- p = skipwhite(p);
-- if (*p == NUL)
-- break;
-- len += 3; /* "," */
-- }
-- else
-- {
-- int charlen = (*mb_ptr2len)(p);
--
-- len += charlen;
-- p += charlen;
-- }
-- }
--
-- buf = alloc(len + 1);
-- if (buf == NULL)
-- {
-- *lenp = 0;
-- return buf;
-- }
--
-- p = arg;
-- q = buf;
-- *q++ = '"';
-- while (*p)
-- {
-- if (p[0] == '\\' && p[1] == '\\')
-- {
-- *q++ = '\\';
-- *q++ = '\\';
-- p += 2;
-- }
-- else if (p[0] == '\\' && VIM_ISWHITE(p[1]))
-- {
-- *q++ = p[1];
-- p += 2;
-- }
-- else if (*p == '\\' || *p == '"')
-- {
-- *q++ = '\\';
-- *q++ = *p++;
-- }
-- else if (VIM_ISWHITE(*p))
-- {
-- p = skipwhite(p);
-- if (*p == NUL)
-- break;
-- *q++ = '"';
-- *q++ = ',';
-- *q++ = '"';
-- }
-- else
-- {
-- MB_COPY_CHAR(p, q);
-- }
-- }
-- *q++ = '"';
-- *q = 0;
--
-- *lenp = len;
-- return buf;
-- }
--
-- static size_t
-- add_cmd_modifier(char_u *buf, char *mod_str, int *multi_mods)
-- {
-- size_t result;
--
-- result = STRLEN(mod_str);
-- if (*multi_mods)
-- result += 1;
-- if (buf != NULL)
-- {
-- if (*multi_mods)
-- STRCAT(buf, " ");
-- STRCAT(buf, mod_str);
-- }
--
-- *multi_mods = 1;
--
-- return result;
-- }
--
-- /*
-- * Check for a <> code in a user command.
-- * "code" points to the '<'. "len" the length of the <> (inclusive).
-- * "buf" is where the result is to be added.
-- * "split_buf" points to a buffer used for splitting, caller should free it.
-- * "split_len" is the length of what "split_buf" contains.
-- * Returns the length of the replacement, which has been added to "buf".
-- * Returns -1 if there was no match, and only the "<" has been copied.
-- */
-- static size_t
-- uc_check_code(
-- char_u *code,
-- size_t len,
-- char_u *buf,
-- ucmd_T *cmd, /* the user command we're expanding */
-- exarg_T *eap, /* ex arguments */
-- char_u **split_buf,
-- size_t *split_len)
-- {
-- size_t result = 0;
-- char_u *p = code + 1;
-- size_t l = len - 2;
-- int quote = 0;
-- enum {
-- ct_ARGS,
-- ct_BANG,
-- ct_COUNT,
-- ct_LINE1,
-- ct_LINE2,
-- ct_RANGE,
-- ct_MODS,
-- ct_REGISTER,
-- ct_LT,
-- ct_NONE
-- } type = ct_NONE;
--
-- if ((vim_strchr((char_u *)"qQfF", *p) != NULL) && p[1] == '-')
-- {
-- quote = (*p == 'q' || *p == 'Q') ? 1 : 2;
-- p += 2;
-- l -= 2;
-- }
--
-- ++l;
-- if (l <= 1)
-- type = ct_NONE;
-- else if (STRNICMP(p, "args>", l) == 0)
-- type = ct_ARGS;
-- else if (STRNICMP(p, "bang>", l) == 0)
-- type = ct_BANG;
-- else if (STRNICMP(p, "count>", l) == 0)
-- type = ct_COUNT;
-- else if (STRNICMP(p, "line1>", l) == 0)
-- type = ct_LINE1;
-- else if (STRNICMP(p, "line2>", l) == 0)
-- type = ct_LINE2;
-- else if (STRNICMP(p, "range>", l) == 0)
-- type = ct_RANGE;
-- else if (STRNICMP(p, "lt>", l) == 0)
-- type = ct_LT;
-- else if (STRNICMP(p, "reg>", l) == 0 || STRNICMP(p, "register>", l) == 0)
-- type = ct_REGISTER;
-- else if (STRNICMP(p, "mods>", l) == 0)
-- type = ct_MODS;
--
-- switch (type)
-- {
-- case ct_ARGS:
-- /* Simple case first */
-- if (*eap->arg == NUL)
-- {
-- if (quote == 1)
-- {
-- result = 2;
-- if (buf != NULL)
-- STRCPY(buf, "''");
-- }
-- else
-- result = 0;
-- break;
-- }
--
-- /* When specified there is a single argument don't split it.
-- * Works for ":Cmd %" when % is "a b c". */
-- if ((eap->argt & NOSPC) && quote == 2)
-- quote = 1;
--
-- switch (quote)
-- {
-- case 0: /* No quoting, no splitting */
-- result = STRLEN(eap->arg);
-- if (buf != NULL)
-- STRCPY(buf, eap->arg);
-- break;
-- case 1: /* Quote, but don't split */
-- result = STRLEN(eap->arg) + 2;
-- for (p = eap->arg; *p; ++p)
-- {
-- if (enc_dbcs != 0 && (*mb_ptr2len)(p) == 2)
-- /* DBCS can contain \ in a trail byte, skip the
-- * double-byte character. */
-- ++p;
-- else
-- if (*p == '\\' || *p == '"')
-- ++result;
-- }
--
-- if (buf != NULL)
-- {
-- *buf++ = '"';
-- for (p = eap->arg; *p; ++p)
-- {
-- if (enc_dbcs != 0 && (*mb_ptr2len)(p) == 2)
-- /* DBCS can contain \ in a trail byte, copy the
-- * double-byte character to avoid escaping. */
-- *buf++ = *p++;
-- else
-- if (*p == '\\' || *p == '"')
-- *buf++ = '\\';
-- *buf++ = *p;
-- }
-- *buf = '"';
-- }
--
-- break;
-- case 2: /* Quote and split (<f-args>) */
-- /* This is hard, so only do it once, and cache the result */
-- if (*split_buf == NULL)
-- *split_buf = uc_split_args(eap->arg, split_len);
--
-- result = *split_len;
-- if (buf != NULL && result != 0)
-- STRCPY(buf, *split_buf);
--
-- break;
-- }
-- break;
--
-- case ct_BANG:
-- result = eap->forceit ? 1 : 0;
-- if (quote)
-- result += 2;
-- if (buf != NULL)
-- {
-- if (quote)
-- *buf++ = '"';
-- if (eap->forceit)
-- *buf++ = '!';
-- if (quote)
-- *buf = '"';
-- }
-- break;
--
-- case ct_LINE1:
-- case ct_LINE2:
-- case ct_RANGE:
-- case ct_COUNT:
-- {
-- char num_buf[20];
-- long num = (type == ct_LINE1) ? eap->line1 :
-- (type == ct_LINE2) ? eap->line2 :
-- (type == ct_RANGE) ? eap->addr_count :
-- (eap->addr_count > 0) ? eap->line2 : cmd->uc_def;
-- size_t num_len;
--
-- sprintf(num_buf, "%ld", num);
-- num_len = STRLEN(num_buf);
-- result = num_len;
--
-- if (quote)
-- result += 2;
--
-- if (buf != NULL)
-- {
-- if (quote)
-- *buf++ = '"';
-- STRCPY(buf, num_buf);
-- buf += num_len;
-- if (quote)
-- *buf = '"';
-- }
--
-- break;
-- }
--
-- case ct_MODS:
-- {
-- int multi_mods = 0;
-- typedef struct {
-- int *varp;
-- char *name;
-- } mod_entry_T;
-- static mod_entry_T mod_entries[] = {
-- #ifdef FEAT_BROWSE_CMD
-- {&cmdmod.browse, "browse"},
-- #endif
-- #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
-- {&cmdmod.confirm, "confirm"},
-- #endif
-- {&cmdmod.hide, "hide"},
-- {&cmdmod.keepalt, "keepalt"},
-- {&cmdmod.keepjumps, "keepjumps"},
-- {&cmdmod.keepmarks, "keepmarks"},
-- {&cmdmod.keeppatterns, "keeppatterns"},
-- {&cmdmod.lockmarks, "lockmarks"},
-- {&cmdmod.noswapfile, "noswapfile"},
-- {NULL, NULL}
-- };
-- int i;
--
-- result = quote ? 2 : 0;
-- if (buf != NULL)
-- {
-- if (quote)
-- *buf++ = '"';
-- *buf = '\0';
-- }
--
-- /* :aboveleft and :leftabove */
-- if (cmdmod.split & WSP_ABOVE)
-- result += add_cmd_modifier(buf, "aboveleft", &multi_mods);
-- /* :belowright and :rightbelow */
-- if (cmdmod.split & WSP_BELOW)
-- result += add_cmd_modifier(buf, "belowright", &multi_mods);
-- /* :botright */
-- if (cmdmod.split & WSP_BOT)
-- result += add_cmd_modifier(buf, "botright", &multi_mods);
--
-- /* the modifiers that are simple flags */
-- for (i = 0; mod_entries[i].varp != NULL; ++i)
-- if (*mod_entries[i].varp)
-- result += add_cmd_modifier(buf, mod_entries[i].name,
-- &multi_mods);
--
-- /* TODO: How to support :noautocmd? */
-- #ifdef HAVE_SANDBOX
-- /* TODO: How to support :sandbox?*/
-- #endif
-- /* :silent */
-- if (msg_silent > 0)
-- result += add_cmd_modifier(buf,
-- emsg_silent > 0 ? "silent!" : "silent", &multi_mods);
-- /* :tab */
-- if (cmdmod.tab > 0)
-- result += add_cmd_modifier(buf, "tab", &multi_mods);
-- /* :topleft */
-- if (cmdmod.split & WSP_TOP)
-- result += add_cmd_modifier(buf, "topleft", &multi_mods);
-- /* TODO: How to support :unsilent?*/
-- /* :verbose */
-- if (p_verbose > 0)
-- result += add_cmd_modifier(buf, "verbose", &multi_mods);
-- /* :vertical */
-- if (cmdmod.split & WSP_VERT)
-- result += add_cmd_modifier(buf, "vertical", &multi_mods);
-- if (quote && buf != NULL)
-- {
-- buf += result - 2;
-- *buf = '"';
-- }
-- break;
-- }
--
-- case ct_REGISTER:
-- result = eap->regname ? 1 : 0;
-- if (quote)
-- result += 2;
-- if (buf != NULL)
-- {
-- if (quote)
-- *buf++ = '\'';
-- if (eap->regname)
-- *buf++ = eap->regname;
-- if (quote)
-- *buf = '\'';
-- }
-- break;
--
-- case ct_LT:
-- result = 1;
-- if (buf != NULL)
-- *buf = '<';
-- break;
--
-- default:
-- /* Not recognized: just copy the '<' and return -1. */
-- result = (size_t)-1;
-- if (buf != NULL)
-- *buf = '<';
-- break;
-- }
--
-- return result;
-- }
--
-- static void
-- do_ucmd(exarg_T *eap)
-- {
-- char_u *buf;
-- char_u *p;
-- char_u *q;
--
-- char_u *start;
-- char_u *end = NULL;
-- char_u *ksp;
-- size_t len, totlen;
--
-- size_t split_len = 0;
-- char_u *split_buf = NULL;
-- ucmd_T *cmd;
-- #ifdef FEAT_EVAL
-- sctx_T save_current_sctx = current_sctx;
-- #endif
--
-- if (eap->cmdidx == CMD_USER)
-- cmd = USER_CMD(eap->useridx);
-- else
-- cmd = USER_CMD_GA(&curbuf->b_ucmds, eap->useridx);
--
-- /*
-- * Replace <> in the command by the arguments.
-- * First round: "buf" is NULL, compute length, allocate "buf".
-- * Second round: copy result into "buf".
-- */
-- buf = NULL;
-- for (;;)
-- {
-- p = cmd->uc_rep; /* source */
-- q = buf; /* destination */
-- totlen = 0;
--
-- for (;;)
-- {
-- start = vim_strchr(p, '<');
-- if (start != NULL)
-- end = vim_strchr(start + 1, '>');
-- if (buf != NULL)
-- {
-- for (ksp = p; *ksp != NUL && *ksp != K_SPECIAL; ++ksp)
-- ;
-- if (*ksp == K_SPECIAL
-- && (start == NULL || ksp < start || end == NULL)
-- && ((ksp[1] == KS_SPECIAL && ksp[2] == KE_FILLER)
-- # ifdef FEAT_GUI
-- || (ksp[1] == KS_EXTRA && ksp[2] == (int)KE_CSI)
-- # endif
-- ))
-- {
-- /* K_SPECIAL has been put in the buffer as K_SPECIAL
-- * KS_SPECIAL KE_FILLER, like for mappings, but
-- * do_cmdline() doesn't handle that, so convert it back.
-- * Also change K_SPECIAL KS_EXTRA KE_CSI into CSI. */
-- len = ksp - p;
-- if (len > 0)
-- {
-- mch_memmove(q, p, len);
-- q += len;
-- }
-- *q++ = ksp[1] == KS_SPECIAL ? K_SPECIAL : CSI;
-- p = ksp + 3;
-- continue;
-- }
-- }
--
-- /* break if no <item> is found */
-- if (start == NULL || end == NULL)
-- break;
--
-- /* Include the '>' */
-- ++end;
--
-- /* Take everything up to the '<' */
-- len = start - p;
-- if (buf == NULL)
-- totlen += len;
-- else
-- {
-- mch_memmove(q, p, len);
-- q += len;
-- }
--
-- len = uc_check_code(start, end - start, q, cmd, eap,
-- &split_buf, &split_len);
-- if (len == (size_t)-1)
-- {
-- /* no match, continue after '<' */
-- p = start + 1;
-- len = 1;
-- }
-- else
-- p = end;
-- if (buf == NULL)
-- totlen += len;
-- else
-- q += len;
-- }
-- if (buf != NULL) /* second time here, finished */
-- {
-- STRCPY(q, p);
-- break;
-- }
--
-- totlen += STRLEN(p); /* Add on the trailing characters */
-- buf = alloc((unsigned)(totlen + 1));
-- if (buf == NULL)
-- {
-- vim_free(split_buf);
-- return;
-- }
-- }
--
-- #ifdef FEAT_EVAL
-- current_sctx.sc_sid = cmd->uc_script_ctx.sc_sid;
-- #endif
-- (void)do_cmdline(buf, eap->getline, eap->cookie,
-- DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
-- #ifdef FEAT_EVAL
-- current_sctx = save_current_sctx;
-- #endif
-- vim_free(buf);
-- vim_free(split_buf);
-- }
--
-- # if defined(FEAT_CMDL_COMPL) || defined(PROTO)
-- static char_u *
-- get_user_command_name(int idx)
-- {
-- return get_user_commands(NULL, idx - (int)CMD_SIZE);
-- }
--
-- /*
-- * Function given to ExpandGeneric() to obtain the list of user command names.
-- */
-- char_u *
-- get_user_commands(expand_T *xp UNUSED, int idx)
-- {
-- if (idx < curbuf->b_ucmds.ga_len)
-- return USER_CMD_GA(&curbuf->b_ucmds, idx)->uc_name;
-- idx -= curbuf->b_ucmds.ga_len;
-- if (idx < ucmds.ga_len)
-- return USER_CMD(idx)->uc_name;
-- return NULL;
-- }
--
-- /*
-- * Function given to ExpandGeneric() to obtain the list of user address type names.
-- */
-- char_u *
-- get_user_cmd_addr_type(expand_T *xp UNUSED, int idx)
-- {
-- return (char_u *)addr_type_complete[idx].name;
-- }
--
-- /*
-- * Function given to ExpandGeneric() to obtain the list of user command
-- * attributes.
-- */
-- char_u *
-- get_user_cmd_flags(expand_T *xp UNUSED, int idx)
-- {
-- static char *user_cmd_flags[] =
-- {"addr", "bang", "bar", "buffer", "complete",
-- "count", "nargs", "range", "register"};
--
-- if (idx >= (int)(sizeof(user_cmd_flags) / sizeof(user_cmd_flags[0])))
-- return NULL;
-- return (char_u *)user_cmd_flags[idx];
-- }
--
-- /*
-- * Function given to ExpandGeneric() to obtain the list of values for -nargs.
-- */
-- char_u *
-- get_user_cmd_nargs(expand_T *xp UNUSED, int idx)
-- {
-- static char *user_cmd_nargs[] = {"0", "1", "*", "?", "+"};
--
-- if (idx >= (int)(sizeof(user_cmd_nargs) / sizeof(user_cmd_nargs[0])))
-- return NULL;
-- return (char_u *)user_cmd_nargs[idx];
-- }
--
-- /*
-- * Function given to ExpandGeneric() to obtain the list of values for -complete.
-- */
-- char_u *
-- get_user_cmd_complete(expand_T *xp UNUSED, int idx)
-- {
-- return (char_u *)command_complete[idx].name;
-- }
-- # endif /* FEAT_CMDL_COMPL */
--
-- /*
-- * Parse address type argument
-- */
-- int
-- parse_addr_type_arg(
-- char_u *value,
-- int vallen,
-- long *argt,
-- int *addr_type_arg)
-- {
-- int i, a, b;
--
-- for (i = 0; addr_type_complete[i].expand != -1; ++i)
-- {
-- a = (int)STRLEN(addr_type_complete[i].name) == vallen;
-- b = STRNCMP(value, addr_type_complete[i].name, vallen) == 0;
-- if (a && b)
-- {
-- *addr_type_arg = addr_type_complete[i].expand;
-- break;
-- }
-- }
--
-- if (addr_type_complete[i].expand == -1)
-- {
-- char_u *err = value;
--
-- for (i = 0; err[i] != NUL && !VIM_ISWHITE(err[i]); i++)
-- ;
-- err[i] = NUL;
-- semsg(_("E180: Invalid address type value: %s"), err);
-- return FAIL;
-- }
--
-- if (*addr_type_arg != ADDR_LINES)
-- *argt |= NOTADR;
--
-- return OK;
-- }
--
-- #endif /* FEAT_USR_CMDS */
--
-- #if defined(FEAT_USR_CMDS) || defined(FEAT_EVAL) || defined(PROTO)
-- /*
-- * Parse a completion argument "value[vallen]".
-- * The detected completion goes in "*complp", argument type in "*argt".
-- * When there is an argument, for function and user defined completion, it's
-- * copied to allocated memory and stored in "*compl_arg".
-- * Returns FAIL if something is wrong.
-- */
-- int
-- parse_compl_arg(
-- char_u *value,
-- int vallen,
-- int *complp,
-- long *argt,
-- char_u **compl_arg UNUSED)
-- {
-- char_u *arg = NULL;
-- # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-- size_t arglen = 0;
-- # endif
-- int i;
-- int valend = vallen;
--
-- /* Look for any argument part - which is the part after any ',' */
-- for (i = 0; i < vallen; ++i)
-- {
-- if (value[i] == ',')
-- {
-- arg = &value[i + 1];
-- # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-- arglen = vallen - i - 1;
-- # endif
-- valend = i;
-- break;
-- }
-- }
--
-- for (i = 0; command_complete[i].expand != 0; ++i)
-- {
-- if ((int)STRLEN(command_complete[i].name) == valend
-- && STRNCMP(value, command_complete[i].name, valend) == 0)
-- {
-- *complp = command_complete[i].expand;
-- if (command_complete[i].expand == EXPAND_BUFFERS)
-- *argt |= BUFNAME;
-- else if (command_complete[i].expand == EXPAND_DIRECTORIES
-- || command_complete[i].expand == EXPAND_FILES)
-- *argt |= XFILE;
-- break;
-- }
-- }
--
-- if (command_complete[i].expand == 0)
-- {
-- semsg(_("E180: Invalid complete value: %s"), value);
-- return FAIL;
-- }
--
-- # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-- if (*complp != EXPAND_USER_DEFINED && *complp != EXPAND_USER_LIST
-- && arg != NULL)
-- # else
-- if (arg != NULL)
-- # endif
-- {
-- emsg(_("E468: Completion argument only allowed for custom completion"));
-- return FAIL;
-- }
--
-- # if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
-- if ((*complp == EXPAND_USER_DEFINED || *complp == EXPAND_USER_LIST)
-- && arg == NULL)
-- {
-- emsg(_("E467: Custom completion requires a function argument"));
-- return FAIL;
-- }
--
-- if (arg != NULL)
-- *compl_arg = vim_strnsave(arg, (int)arglen);
-- # endif
-- return OK;
-- }
--
-- int
-- cmdcomplete_str_to_type(char_u *complete_str)
-- {
-- int i;
--
-- for (i = 0; command_complete[i].expand != 0; ++i)
-- if (STRCMP(complete_str, command_complete[i].name) == 0)
-- return command_complete[i].expand;
--
-- return EXPAND_NOTHING;
-- }
-- #endif
--
- static void
- ex_colorscheme(exarg_T *eap)
- {
---- 5549,5559 ----
-*** ../vim-8.1.1209/src/proto/ex_docmd.pro 2019-01-13 23:38:33.407773189 +0100
---- src/proto/ex_docmd.pro 2019-04-26 23:39:53.321890880 +0200
-***************
-*** 19,34 ****
- char_u *find_nextcmd(char_u *p);
- char_u *check_nextcmd(char_u *p);
- char_u *get_command_name(expand_T *xp, int idx);
-- void ex_comclear(exarg_T *eap);
-- void uc_clear(garray_T *gap);
-- char_u *get_user_commands(expand_T *xp, int idx);
-- char_u *get_user_cmd_addr_type(expand_T *xp, int idx);
-- char_u *get_user_cmd_flags(expand_T *xp, int idx);
-- char_u *get_user_cmd_nargs(expand_T *xp, int idx);
-- char_u *get_user_cmd_complete(expand_T *xp, int idx);
-- int parse_addr_type_arg(char_u *value, int vallen, long *argt, int *addr_type_arg);
-- int parse_compl_arg(char_u *value, int vallen, int *complp, long *argt, char_u **compl_arg);
-- int cmdcomplete_str_to_type(char_u *complete_str);
- void not_exiting(void);
- void tabpage_close(int forceit);
- void tabpage_close_other(tabpage_T *tp, int forceit);
---- 19,24 ----
-*** ../vim-8.1.1209/src/ex_getln.c 2019-04-11 13:45:53.125298538 +0200
---- src/ex_getln.c 2019-04-26 23:26:22.726894948 +0200
-***************
-*** 111,117 ****
- # ifdef FEAT_CMDHIST
- static char_u *get_history_arg(expand_T *xp, int idx);
- # endif
-! # if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL)
- static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file);
- static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file);
- # endif
---- 111,117 ----
- # ifdef FEAT_CMDHIST
- static char_u *get_history_arg(expand_T *xp, int idx);
- # endif
-! # if defined(FEAT_EVAL)
- static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file);
- static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file);
- # endif
-***************
-*** 939,945 ****
- {
- xpc.xp_context = ccline.xp_context;
- xpc.xp_pattern = ccline.cmdbuff;
-! # if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)
- xpc.xp_arg = ccline.xp_arg;
- # endif
- }
---- 939,945 ----
- {
- xpc.xp_context = ccline.xp_context;
- xpc.xp_pattern = ccline.cmdbuff;
-! # if defined(FEAT_CMDL_COMPL)
- xpc.xp_arg = ccline.xp_arg;
- # endif
- }
-***************
-*** 4210,4216 ****
- #endif
- xp->xp_numfiles = -1;
- xp->xp_files = NULL;
-! #if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
- xp->xp_arg = NULL;
- #endif
- xp->xp_line = NULL;
---- 4210,4216 ----
- #endif
- xp->xp_numfiles = -1;
- xp->xp_files = NULL;
-! #if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
- xp->xp_arg = NULL;
- #endif
- xp->xp_line = NULL;
-***************
-*** 4879,4885 ****
- {
- xp->xp_context = ccline.xp_context;
- xp->xp_pattern = ccline.cmdbuff;
-! # if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)
- xp->xp_arg = ccline.xp_arg;
- # endif
- }
---- 4879,4885 ----
- {
- xp->xp_context = ccline.xp_context;
- xp->xp_pattern = ccline.cmdbuff;
-! # if defined(FEAT_CMDL_COMPL)
- xp->xp_arg = ccline.xp_arg;
- # endif
- }
-***************
-*** 5130,5136 ****
- char *directories[] = {"syntax", "indent", "ftplugin", NULL};
- return ExpandRTDir(pat, 0, num_file, file, directories);
- }
-! # if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL)
- if (xp->xp_context == EXPAND_USER_LIST)
- return ExpandUserList(xp, num_file, file);
- # endif
---- 5130,5136 ----
- char *directories[] = {"syntax", "indent", "ftplugin", NULL};
- return ExpandRTDir(pat, 0, num_file, file, directories);
- }
-! # if defined(FEAT_EVAL)
- if (xp->xp_context == EXPAND_USER_LIST)
- return ExpandUserList(xp, num_file, file);
- # endif
-***************
-*** 5149,5155 ****
- ret = ExpandSettings(xp, &regmatch, num_file, file);
- else if (xp->xp_context == EXPAND_MAPPINGS)
- ret = ExpandMappings(&regmatch, num_file, file);
-! # if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL)
- else if (xp->xp_context == EXPAND_USER_DEFINED)
- ret = ExpandUserDefined(xp, &regmatch, num_file, file);
- # endif
---- 5149,5155 ----
- ret = ExpandSettings(xp, &regmatch, num_file, file);
- else if (xp->xp_context == EXPAND_MAPPINGS)
- ret = ExpandMappings(&regmatch, num_file, file);
-! # if defined(FEAT_EVAL)
- else if (xp->xp_context == EXPAND_USER_DEFINED)
- ret = ExpandUserDefined(xp, &regmatch, num_file, file);
- # endif
-***************
-*** 5170,5182 ****
- #ifdef FEAT_CMDHIST
- {EXPAND_HISTORY, get_history_arg, TRUE, TRUE},
- #endif
-- #ifdef FEAT_USR_CMDS
- {EXPAND_USER_COMMANDS, get_user_commands, FALSE, TRUE},
- {EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, FALSE, TRUE},
- {EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE, TRUE},
- {EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE, TRUE},
- {EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE, TRUE},
-- #endif
- #ifdef FEAT_EVAL
- {EXPAND_USER_VARS, get_user_var_name, FALSE, TRUE},
- {EXPAND_FUNCTIONS, get_function_name, FALSE, TRUE},
---- 5170,5180 ----
-***************
-*** 5473,5479 ****
- }
-
-
-! # if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL)
- /*
- * Call "user_expand_func()" to invoke a user defined Vim script function and
- * return the result (either a string or a List).
---- 5471,5477 ----
- }
-
-
-! # if defined(FEAT_EVAL)
- /*
- * Call "user_expand_func()" to invoke a user defined Vim script function and
- * return the result (either a string or a List).
-*** ../vim-8.1.1209/src/feature.h 2019-03-30 21:19:16.426170240 +0100
---- src/feature.h 2019-04-26 23:27:34.074374224 +0200
-***************
-*** 379,388 ****
-
- /*
- * +user_commands Allow the user to define his own commands.
- */
-- #ifdef FEAT_NORMAL
-- # define FEAT_USR_CMDS
-- #endif
-
- /*
- * +printer ":hardcopy" command
---- 379,386 ----
-
- /*
- * +user_commands Allow the user to define his own commands.
-+ * Now always enabled.
- */
-
- /*
- * +printer ":hardcopy" command
-*** ../vim-8.1.1209/src/macros.h 2019-03-30 18:46:57.356077354 +0100
---- src/macros.h 2019-04-26 23:12:15.806808513 +0200
-***************
-*** 336,338 ****
---- 336,341 ----
- (p) = NULL; \
- } \
- } while (0)
-+
-+ /* Wether a command index indicates a user command. */
-+ #define IS_USER_CMDIDX(idx) ((int)(idx) < 0)
-*** ../vim-8.1.1209/src/misc2.c 2019-03-30 13:53:26.174425093 +0100
---- src/misc2.c 2019-04-26 23:51:39.458250238 +0200
-***************
-*** 1082,1091 ****
- ui_remove_balloon();
- # endif
-
-! # if defined(FEAT_USR_CMDS)
-! /* Clear user commands (before deleting buffers). */
- ex_comclear(NULL);
-- # endif
-
- # ifdef FEAT_MENU
- /* Clear menus. */
---- 1082,1089 ----
- ui_remove_balloon();
- # endif
-
-! // Clear user commands (before deleting buffers).
- ex_comclear(NULL);
-
- # ifdef FEAT_MENU
- /* Clear menus. */
-***************
-*** 1130,1136 ****
---- 1128,1136 ----
- free_search_patterns();
- free_old_sub();
- free_last_insert();
-+ # if defined(FEAT_INS_EXPAND)
- free_insexpand_stuff();
-+ # endif
- free_prev_shellcmd();
- free_regexp_stuff();
- free_tag_stuff();
-*** ../vim-8.1.1209/src/proto.h 2019-04-21 11:34:36.335256531 +0200
---- src/proto.h 2019-04-26 23:05:42.872538740 +0200
-***************
-*** 227,232 ****
---- 227,233 ----
- # endif
- # include "ui.pro"
- # include "undo.pro"
-+ # include "usercmd.pro"
- # include "userfunc.pro"
- # include "version.pro"
- # include "window.pro"
-*** ../vim-8.1.1209/src/structs.h 2019-04-25 22:21:56.931749183 +0200
---- src/structs.h 2019-04-26 23:28:26.458006469 +0200
-***************
-*** 549,555 ****
- int xp_context; /* type of expansion */
- char_u *xp_pattern; /* start of item to expand */
- int xp_pattern_len; /* bytes in xp_pattern before cursor */
-! #if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
- char_u *xp_arg; /* completion function */
- sctx_T xp_script_ctx; /* SCTX for completion function */
- #endif
---- 549,555 ----
- int xp_context; /* type of expansion */
- char_u *xp_pattern; /* start of item to expand */
- int xp_pattern_len; /* bytes in xp_pattern before cursor */
-! #if defined(FEAT_EVAL) && defined(FEAT_CMDL_COMPL)
- char_u *xp_arg; /* completion function */
- sctx_T xp_script_ctx; /* SCTX for completion function */
- #endif
-***************
-*** 2143,2152 ****
- /* First abbreviation local to a buffer. */
- mapblock_T *b_first_abbr;
- #endif
-! #ifdef FEAT_USR_CMDS
-! /* User commands local to the buffer. */
- garray_T b_ucmds;
-- #endif
- /*
- * start and end of an operator, also used for '[ and ']
- */
---- 2143,2150 ----
- /* First abbreviation local to a buffer. */
- mapblock_T *b_first_abbr;
- #endif
-! // User commands local to the buffer.
- garray_T b_ucmds;
- /*
- * start and end of an operator, also used for '[ and ']
- */
-*** ../vim-8.1.1209/src/version.c 2019-04-26 22:33:44.896723710 +0200
---- src/version.c 2019-04-26 23:33:32.156048100 +0200
-***************
-*** 672,682 ****
- #else
- "-toolbar",
- #endif
-- #ifdef FEAT_USR_CMDS
- "+user_commands",
-- #else
-- "-user_commands",
-- #endif
- #ifdef FEAT_VARTABS
- "+vartabs",
- #else
---- 672,678 ----
-*** ../vim-8.1.1209/runtime/doc/eval.txt 2019-04-20 14:39:42.796386124 +0200
---- runtime/doc/eval.txt 2019-04-27 12:38:38.744951183 +0200
-***************
-*** 10491,10497 ****
- ttyout output is a terminal (tty)
- unix Unix version of Vim. *+unix*
- unnamedplus Compiled with support for "unnamedplus" in 'clipboard'
-! user_commands User-defined commands.
- vcon Win32: Virtual console support is working, can use
- 'termguicolors'. Also see |+vtp|.
- vertsplit Compiled with vertically split windows |:vsplit|.
---- 10550,10556 ----
- ttyout output is a terminal (tty)
- unix Unix version of Vim. *+unix*
- unnamedplus Compiled with support for "unnamedplus" in 'clipboard'
-! user_commands User-defined commands. (always true)
- vcon Win32: Virtual console support is working, can use
- 'termguicolors'. Also see |+vtp|.
- vertsplit Compiled with vertically split windows |:vsplit|.
-***************
-*** 10501,10506 ****
---- 10560,10566 ----
- viminfo Compiled with viminfo support.
- vimscript-1 Compiled Vim script version 1 support
- vimscript-2 Compiled Vim script version 2 support
-+ vimscript-3 Compiled Vim script version 3 support
- virtualedit Compiled with 'virtualedit' option. (always true)
- visual Compiled with Visual mode. (always true)
- visualextra Compiled with extra Visual mode commands. (always
-***************
-*** 12700,12706 ****
-
- These items are not allowed in the sandbox:
- - changing the buffer text
-! - defining or changing mapping, autocommands, functions, user commands
- - setting certain options (see |option-summary|)
- - setting certain v: variables (see |v:var|) *E794*
- - executing a shell command
---- 12771,12777 ----
-
- These items are not allowed in the sandbox:
- - changing the buffer text
-! - defining or changing mapping, autocommands, user commands
- - setting certain options (see |option-summary|)
- - setting certain v: variables (see |v:var|) *E794*
- - executing a shell command
-*** ../vim-8.1.1209/runtime/doc/various.txt 2019-01-11 14:37:16.689248837 +0100
---- runtime/doc/various.txt 2019-04-27 12:40:20.376390811 +0200
-***************
-*** 458,464 ****
- N *+timers* the |timer_start()| function
- N *+title* Setting the window 'title' and 'icon'
- N *+toolbar* |gui-toolbar|
-! N *+user_commands* User-defined commands. |user-commands|
- B *+vartabs* Variable-width tabstops. |'vartabstop'|
- N *+viminfo* |'viminfo'|
- *+vertsplit* Vertically split windows |:vsplit|; Always enabled
---- 456,463 ----
- N *+timers* the |timer_start()| function
- N *+title* Setting the window 'title' and 'icon'
- N *+toolbar* |gui-toolbar|
-! T *+user_commands* User-defined commands. |user-commands|
-! Always enabled since 8.1.1210.
- B *+vartabs* Variable-width tabstops. |'vartabstop'|
- N *+viminfo* |'viminfo'|
- *+vertsplit* Vertically split windows |:vsplit|; Always enabled
-*** ../vim-8.1.1209/src/version.c 2019-04-26 22:33:44.896723710 +0200
---- src/version.c 2019-04-26 23:33:32.156048100 +0200
-***************
-*** 773,774 ****
---- 769,772 ----
- { /* Add new patch number below this line */
-+ /**/
-+ 1210,
- /**/
-
---
-Shit makes the flowers grow and that's beautiful
-
- /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
-/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
-\\\ an exciting new programming language -- http://www.Zimbu.org ///
- \\\ help me help AIDS victims -- http://ICCF-Holland.org ///