# HG changeset patch # User Christian Brabandt # Date 1465071305 -7200 # Node ID f7fb117883ba6fa58c6db7395b88b87e191afd68 # Parent a169b470d24d776674c55e99a75d35261f6367b9 commit https://github.com/vim/vim/commit/63a60ded3fd584847a05dccf058026e682abad90 Author: Bram Moolenaar Date: Sat Jun 4 22:08:55 2016 +0200 patch 7.4.1898 Problem: User commands don't support modifiers. Solution: Add the item. (Yegappan Lakshmanan, closes https://github.com/vim/vim/issues/829) diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1411,6 +1411,27 @@ The valid escape sequences are (See the '-bang' attribute) Expands to a ! if the command was executed with a ! modifier, otherwise expands to nothing. + ** + The command modifiers, if specified. Otherwise, expands to + nothing. Supported modifiers are |aboveleft|, |belowright|, + |botright|, |browse|, |confirm|, |hide|, |keepalt|, + |keepjumps|, |keepmarks|, |keeppatterns|, |lockmarks|, + |noswapfile|, |silent|, |tab|, |topleft|, |verbose|, and + |vertical|. + Examples: > + command! -nargs=+ -complete=file MyEdit + \ for f in expand(, 0, 1) | + \ exe ' split ' . f | + \ endfor + + function! SpecialEdit(files, mods) + for f in expand(a:files, 0, 1) + exe a:mods . ' split ' . f + endfor + endfunction + command! -nargs=+ -complete=file Sedit + \ call SpecialEdit(, ) +< ** ** (See the '-register' attribute) The optional register, if specified. Otherwise, expands to nothing. diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -6413,6 +6413,26 @@ uc_split_args(char_u *arg, size_t *lenp) 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). @@ -6436,8 +6456,8 @@ uc_check_code( 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_REGISTER, - ct_LT, ct_NONE } type = ct_NONE; + enum { ct_ARGS, ct_BANG, ct_COUNT, ct_LINE1, ct_LINE2, ct_MODS, + ct_REGISTER, ct_LT, ct_NONE } type = ct_NONE; if ((vim_strchr((char_u *)"qQfF", *p) != NULL) && p[1] == '-') { @@ -6463,6 +6483,8 @@ uc_check_code( 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) { @@ -6586,6 +6608,90 @@ uc_check_code( 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'; + } + +#ifdef FEAT_WINDOWS + /* :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); +#endif + + /* 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); +#ifdef FEAT_WINDOWS + /* :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); +#endif + /* TODO: How to support :unsilent?*/ + /* :verbose */ + if (p_verbose > 0) + result += add_cmd_modifier(buf, "verbose", &multi_mods); +#ifdef FEAT_WINDOWS + /* :vertical */ + if (cmdmod.split & WSP_VERT) + result += add_cmd_modifier(buf, "vertical", &multi_mods); +#endif + if (quote && buf != NULL) + { + buf += result - 2; + *buf = '"'; + } + break; + } + case ct_REGISTER: result = eap->regname ? 1 : 0; if (quote) diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -179,6 +179,7 @@ NEW_TESTS = test_arglist.res \ test_perl.res \ test_quickfix.res \ test_syntax.res \ + test_usercommands.res \ test_viminfo.res \ test_viml.res \ test_visual.res \ diff --git a/src/testdir/test_usercommands.vim b/src/testdir/test_usercommands.vim new file mode 100644 --- /dev/null +++ b/src/testdir/test_usercommands.vim @@ -0,0 +1,48 @@ +" Tests for user defined commands + +" Test for in user defined commands +function Test_cmdmods() + let g:mods = '' + + command! -nargs=* MyCmd let g:mods .= ' ' + + MyCmd + aboveleft MyCmd + belowright MyCmd + botright MyCmd + browse MyCmd + confirm MyCmd + hide MyCmd + keepalt MyCmd + keepjumps MyCmd + keepmarks MyCmd + keeppatterns MyCmd + lockmarks MyCmd + noswapfile MyCmd + silent MyCmd + tab MyCmd + topleft MyCmd + verbose MyCmd + vertical MyCmd + + aboveleft belowright botright browse confirm hide keepalt keepjumps + \ keepmarks keeppatterns lockmarks noswapfile silent tab + \ topleft verbose vertical MyCmd + + call assert_equal(' aboveleft belowright botright browse confirm ' . + \ 'hide keepalt keepjumps keepmarks keeppatterns lockmarks ' . + \ 'noswapfile silent tab topleft verbose vertical aboveleft ' . + \ 'belowright botright browse confirm hide keepalt keepjumps ' . + \ 'keepmarks keeppatterns lockmarks noswapfile silent tab topleft ' . + \ 'verbose vertical ', g:mods) + + let g:mods = '' + command! -nargs=* MyQCmd let g:mods .= ' ' + + vertical MyQCmd + call assert_equal('"vertical" ', g:mods) + + delcommand MyCmd + delcommand MyQCmd + unlet g:mods +endfunction diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1898, +/**/ 1897, /**/ 1896,