diff options
Diffstat (limited to 'src/nvim/ex_docmd.c')
-rw-r--r-- | src/nvim/ex_docmd.c | 175 |
1 files changed, 138 insertions, 37 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 1e54f03ba0..45407b7f12 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -36,7 +36,6 @@ #include "nvim/menu.h" #include "nvim/message.h" #include "nvim/misc1.h" -#include "nvim/misc2.h" #include "nvim/keymap.h" #include "nvim/file_search.h" #include "nvim/garray.h" @@ -345,7 +344,8 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, msg_list = saved_msg_list; return FAIL; } - ++call_depth; + call_depth++; + start_batch_changes(); cstack.cs_idx = -1; cstack.cs_looplevel = 0; @@ -952,7 +952,8 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, did_endif = FALSE; /* in case do_cmdline used recursively */ - --call_depth; + call_depth--; + end_batch_changes(); return retval; } @@ -1325,24 +1326,24 @@ static char_u * do_one_cmd(char_u **cmdlinep, case 'c': if (!checkforcmd(&ea.cmd, "confirm", 4)) break; - cmdmod.confirm = TRUE; + cmdmod.confirm = true; continue; case 'k': if (checkforcmd(&ea.cmd, "keepmarks", 3)) { - cmdmod.keepmarks = TRUE; + cmdmod.keepmarks = true; continue; } if (checkforcmd(&ea.cmd, "keepalt", 5)) { - cmdmod.keepalt = TRUE; + cmdmod.keepalt = true; continue; } if (checkforcmd(&ea.cmd, "keeppatterns", 5)) { - cmdmod.keeppatterns = TRUE; + cmdmod.keeppatterns = true; continue; } if (!checkforcmd(&ea.cmd, "keepjumps", 5)) break; - cmdmod.keepjumps = TRUE; + cmdmod.keepjumps = true; continue; /* ":hide" and ":hide | cmd" are not modifiers */ @@ -1350,11 +1351,11 @@ static char_u * do_one_cmd(char_u **cmdlinep, || *p == NUL || ends_excmd(*p)) break; ea.cmd = p; - cmdmod.hide = TRUE; + cmdmod.hide = true; continue; case 'l': if (checkforcmd(&ea.cmd, "lockmarks", 3)) { - cmdmod.lockmarks = TRUE; + cmdmod.lockmarks = true; continue; } @@ -4362,12 +4363,15 @@ static void ex_autocmd(exarg_T *eap) */ static void ex_doautocmd(exarg_T *eap) { - char_u *arg = eap->arg; + char_u *arg = eap->arg; int call_do_modelines = check_nomodeline(&arg); + bool did_aucmd; - (void)do_doautocmd(arg, TRUE); - if (call_do_modelines) /* Only when there is no <nomodeline>. */ + (void)do_doautocmd(arg, true, &did_aucmd); + // Only when there is no <nomodeline>. + if (call_do_modelines && did_aucmd) { do_modelines(0); + } } /* @@ -5154,6 +5158,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 +5200,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 +5209,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 +5336,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" }, + { &cmdmod.confirm, "confirm" }, + { &cmdmod.hide, "hide" }, + { &cmdmod.keepalt, "keepalt" }, + { &cmdmod.keepjumps, "keepjumps" }, + { &cmdmod.keepmarks, "keepmarks" }, + { &cmdmod.keeppatterns, "keeppatterns" }, + { &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) @@ -9360,7 +9466,7 @@ static void ex_filetype(exarg_T *eap) } } if (*arg == 'd') { - (void)do_doautocmd((char_u *)"filetypedetect BufRead", TRUE); + (void)do_doautocmd((char_u *)"filetypedetect BufRead", true, NULL); do_modelines(0); } } else if (STRCMP(arg, "off") == 0) { @@ -9511,20 +9617,15 @@ static void ex_foldopen(exarg_T *eap) static void ex_folddo(exarg_T *eap) { - linenr_T lnum; - - start_global_changes(); - - /* First set the marks for all lines closed/open. */ - for (lnum = eap->line1; lnum <= eap->line2; ++lnum) - if (hasFolding(lnum, NULL, NULL) == (eap->cmdidx == CMD_folddoclosed)) + // First set the marks for all lines closed/open. + for (linenr_T lnum = eap->line1; lnum <= eap->line2; ++lnum) { + if (hasFolding(lnum, NULL, NULL) == (eap->cmdidx == CMD_folddoclosed)) { ml_setmarked(lnum); + } + } - /* Execute the command on the marked lines. */ - global_exe(eap->arg); - ml_clearmarked(); /* clear rest of the marks */ - - end_global_changes(); + global_exe(eap->arg); // Execute the command on the marked lines. + ml_clearmarked(); // clear rest of the marks } static void ex_terminal(exarg_T *eap) |