vim-patch:7.4.1898

Problem:    User commands don't support modifiers.
Solution:   Add the <mods> item. (Yegappan Lakshmanan, closes vim/vim#829)

63a60ded3f
This commit is contained in:
Anmol Sethi 2016-08-10 23:52:25 -04:00
parent 4d253b4df5
commit 8a7b15cf35
No known key found for this signature in database
GPG Key ID: 427400A70839B0ED
5 changed files with 182 additions and 12 deletions

View File

@ -1406,6 +1406,27 @@ The valid escape sequences are
<bang> (See the '-bang' attribute) Expands to a ! if the
command was executed with a ! modifier, otherwise
expands to nothing.
*<mods>*
<mods> 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(<q-args>, 0, 1) |
\ exe '<mods> 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(<q-args>, <q-mods>)
<
*<reg>* *<register>*
<reg> (See the '-register' attribute) The optional register,
if specified. Otherwise, expands to nothing. <register>

View File

@ -5154,6 +5154,24 @@ static char_u *uc_split_args(char_u *arg, size_t *lenp)
return buf;
}
static size_t add_cmd_modifier(char_u *buf, char *mod_str, bool *multi_mods)
{
size_t result = STRLEN(mod_str);
if (*multi_mods) {
result++;
}
if (buf != NULL) {
if (*multi_mods) {
STRCAT(buf, " ");
}
STRCAT(buf, mod_str);
}
*multi_mods = true;
return result;
}
/*
* Check for a <> code in a user command.
* "code" points to the '<'. "len" the length of the <> (inclusive).
@ -5178,8 +5196,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] == '-') {
quote = (*p == 'q' || *p == 'Q') ? 1 : 2;
@ -5187,23 +5205,26 @@ uc_check_code (
l -= 2;
}
++l;
if (l <= 1)
l++;
if (l <= 1) {
type = ct_NONE;
else if (STRNICMP(p, "args>", l) == 0)
} else if (STRNICMP(p, "args>", l) == 0) {
type = ct_ARGS;
else if (STRNICMP(p, "bang>", l) == 0)
} else if (STRNICMP(p, "bang>", l) == 0) {
type = ct_BANG;
else if (STRNICMP(p, "count>", l) == 0)
} else if (STRNICMP(p, "count>", l) == 0) {
type = ct_COUNT;
else if (STRNICMP(p, "line1>", l) == 0)
} else if (STRNICMP(p, "line1>", l) == 0) {
type = ct_LINE1;
else if (STRNICMP(p, "line2>", l) == 0)
} else if (STRNICMP(p, "line2>", l) == 0) {
type = ct_LINE2;
else if (STRNICMP(p, "lt>", l) == 0)
} else if (STRNICMP(p, "lt>", l) == 0) {
type = ct_LT;
else if (STRNICMP(p, "reg>", l) == 0 || STRNICMP(p, "register>", l) == 0)
} 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:
@ -5311,6 +5332,87 @@ uc_check_code (
break;
}
case ct_MODS:
{
result = quote ? 2 : 0;
if (buf != NULL) {
if (quote) {
*buf++ = '"';
}
*buf = '\0';
}
bool multi_mods = false;
// :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);
}
typedef struct {
bool *set;
char *name;
} mod_entry_T;
static mod_entry_T mod_entries[] = {
{ &cmdmod.browse, "browse" },
{ (bool *)&cmdmod.confirm, "confirm" },
{ (bool *)&cmdmod.hide, "hide" },
{ (bool *)&cmdmod.keepalt, "keepalt" },
{ (bool *)&cmdmod.keepjumps, "keepjumps" },
{ (bool *)&cmdmod.keepmarks, "keepmarks" },
{ (bool *)&cmdmod.keeppatterns, "keeppatterns" },
{ (bool *)&cmdmod.lockmarks, "lockmarks" },
{ &cmdmod.noswapfile, "noswapfile" }
};
// the modifiers that are simple flags
for (size_t i = 0; i < ARRAY_SIZE(mod_entries); i++) {
if (*mod_entries[i].set) {
result += add_cmd_modifier(buf, mod_entries[i].name, &multi_mods);
}
}
// TODO(vim): How to support :noautocmd?
// TODO(vim): How to support :sandbox
// :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(vim): 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)

View File

@ -36,6 +36,7 @@ NEW_TESTS = \
test_help_tagjump.res \
test_langmap.res \
test_syntax.res \
test_usercommands.res \
test_timers.res \
test_viml.res \
test_visual.res \

View File

@ -0,0 +1,46 @@
" Tests for user defined commands
" Test for <mods> in user defined commands
function Test_cmdmods()
let g:mods = ''
command! -nargs=* MyCmd let g:mods .= '<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 .= '<q-mods> '
vertical MyQCmd
call assert_equal('"vertical" ', g:mods)
delcommand MyCmd
delcommand MyQCmd
unlet g:mods
endfunction

View File

@ -378,7 +378,7 @@ static int included_patches[] = {
// 1901 NA
// 1900,
// 1899 NA
// 1898,
1898,
// 1897,
// 1896,
// 1895,