Patch 8.2.1897
Problem: Command modifiers are saved and set inconsistently.
Solution: Separate parsing and applying command modifiers. Save values in
cmdmod_T.
Files: src/structs.h, src/ex_docmd.c, src/proto/
ex_docmd.pro,
src/ex_cmds.h, src/vim9compile.c
*** ../vim-8.2.1896/src/structs.h 2020-10-23 18:02:28.707453763 +0200
--- src/structs.h 2020-10-24 17:08:45.893235506 +0200
***************
*** 625,630 ****
--- 625,631 ----
*/
typedef struct
{
+ int cmod_flags; // CMOD_ flags, see below
int hide; // TRUE when ":hide" was used
# ifdef FEAT_BROWSE_CMD
int browse; // TRUE to invoke file dialog
***************
*** 640,652 ****
int lockmarks; // TRUE when ":lockmarks" was used
int keeppatterns; // TRUE when ":keeppatterns" was used
int noswapfile; // TRUE when ":noswapfile" was used
- char_u *save_ei; // saved value of 'eventignore'
regmatch_T filter_regmatch; // set by :filter /pat/
int filter_force; // set for :filter!
! int msg_silent; // TRUE when ":silent" was used
! int emsg_silent; // TRUE when ":silent!" was used
} cmdmod_T;
#define MF_SEED_LEN 8
struct memfile
--- 641,669 ----
int lockmarks; // TRUE when ":lockmarks" was used
int keeppatterns; // TRUE when ":keeppatterns" was used
int noswapfile; // TRUE when ":noswapfile" was used
regmatch_T filter_regmatch; // set by :filter /pat/
int filter_force; // set for :filter!
!
! int cmod_verbose; // non-zero to set 'verbose'
!
! // values for undo_cmdmod()
! char_u *cmod_save_ei; // saved value of 'eventignore'
! #ifdef HAVE_SANDBOX
! int cmod_did_sandbox; // set when "sandbox" was incremented
! #endif
! long cmod_verbose_save; // if 'verbose' was set: value of
! // p_verbose plus one
! int cmod_save_msg_silent; // if non-zero: saved value of
! // msg_silent + 1
! int cmod_did_esilent; // incremented when emsg_silent is
} cmdmod_T;
+ #define CMOD_SANDBOX 0x01
+ #define CMOD_SILENT 0x02
+ #define CMOD_ERRSILENT 0x04
+ #define CMOD_UNSILENT 0x08
+ #define CMOD_NOAUTOCMD 0x10
+
#define MF_SEED_LEN 8
struct memfile
*** ../vim-8.2.1896/src/ex_docmd.c 2020-10-23 18:51:03.531271374 +0200
--- src/ex_docmd.c 2020-10-24 17:10:01.761070302 +0200
***************
*** 1764,1769 ****
--- 1764,1770 ----
#endif
if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
goto doend;
+ apply_cmdmod(&cmdmod);
after_modifier = ea.cmd;
***************
*** 2515,2526 ****
// The :try command saves the emsg_silent flag, reset it here when
// ":silent! try" was used, it should only apply to :try itself.
! if (ea.cmdidx == CMD_try && ea.did_esilent > 0)
{
! emsg_silent -= ea.did_esilent;
if (emsg_silent < 0)
emsg_silent = 0;
! ea.did_esilent = 0;
}
/*
--- 2516,2527 ----
// The :try command saves the emsg_silent flag, reset it here when
// ":silent! try" was used, it should only apply to :try itself.
! if (ea.cmdidx == CMD_try && cmdmod.cmod_did_esilent > 0)
{
! emsg_silent -= cmdmod.cmod_did_esilent;
if (emsg_silent < 0)
emsg_silent = 0;
! cmdmod.cmod_did_esilent = 0;
}
/*
***************
*** 2597,2611 ****
? cmdnames[(int)ea.cmdidx].cmd_name : (char_u *)NULL);
#endif
! undo_cmdmod(&ea, save_msg_scroll);
cmdmod = save_cmdmod;
reg_executing = save_reg_executing;
- #ifdef HAVE_SANDBOX
- if (ea.did_sandbox)
- --sandbox;
- #endif
-
if (ea.nextcmd && *ea.nextcmd == NUL) // not really a next command
ea.nextcmd = NULL;
--- 2598,2607 ----
? cmdnames[(int)ea.cmdidx].cmd_name : (char_u *)NULL);
#endif
! undo_cmdmod(save_msg_scroll);
cmdmod = save_cmdmod;
reg_executing = save_reg_executing;
if (ea.nextcmd && *ea.nextcmd == NUL) // not really a next command
ea.nextcmd = NULL;
***************
*** 2641,2650 ****
* - Set ex_pressedreturn for an empty command line.
* - set msg_silent for ":silent"
* - set 'eventignore' to "all" for ":noautocmd"
- * - set p_verbose for ":verbose"
- * - Increment "sandbox" for ":sandbox"
* When "skip_only" is TRUE the global variables are not changed, except for
* "cmdmod".
* Return FAIL when the command is not to be executed.
* May set "errormsg" to an error message.
*/
--- 2637,2647 ----
* - Set ex_pressedreturn for an empty command line.
* - set msg_silent for ":silent"
* - set 'eventignore' to "all" for ":noautocmd"
* When "skip_only" is TRUE the global variables are not changed, except for
* "cmdmod".
+ * Call apply_cmdmod() to get the side effects of the modifiers:
+ * - Increment "sandbox" for ":sandbox"
+ * - set p_verbose for ":verbose"
* Return FAIL when the command is not to be executed.
* May set "errormsg" to an error message.
*/
***************
*** 2655,2662 ****
int starts_with_colon = FALSE;
CLEAR_FIELD(cmdmod);
- eap->verbose_save = -1;
- eap->save_msg_silent = -1;
// Repeat until no more command modifiers are found.
for (;;)
--- 2652,2657 ----
***************
*** 2800,2813 ****
case 'n': if (checkforcmd(&eap->cmd, "noautocmd", 3))
{
! if (cmdmod.save_ei == NULL && !skip_only)
! {
! // Set 'eventignore' to "all". Restore the
! // existing option value later.
! cmdmod.save_ei = vim_strsave(p_ei);
! set_string_option_direct((char_u *)"ei", -1,
! (char_u *)"all", OPT_FREE, SID_NONE);
! }
continue;
}
if (!checkforcmd(&eap->cmd, "noswapfile", 3))
--- 2795,2801 ----
case 'n': if (checkforcmd(&eap->cmd, "noautocmd", 3))
{
! cmdmod.cmod_flags |= CMOD_NOAUTOCMD;
continue;
}
if (!checkforcmd(&eap->cmd, "noswapfile", 3))
***************
*** 2822,2858 ****
case 's': if (checkforcmd(&eap->cmd, "sandbox", 3))
{
! #ifdef HAVE_SANDBOX
! if (!skip_only)
! {
! if (!eap->did_sandbox)
! ++sandbox;
! eap->did_sandbox = TRUE;
! }
! #endif
continue;
}
if (!checkforcmd(&eap->cmd, "silent", 3))
break;
! if (!skip_only)
! {
! if (eap->save_msg_silent == -1)
! eap->save_msg_silent = msg_silent;
! ++msg_silent;
! }
if (*eap->cmd == '!' && !VIM_ISWHITE(eap->cmd[-1]))
{
// ":silent!", but not "silent !cmd"
eap->cmd = skipwhite(eap->cmd + 1);
! if (!skip_only)
! {
! ++emsg_silent;
! ++eap->did_esilent;
! }
! cmdmod.emsg_silent = TRUE;
}
- else
- cmdmod.msg_silent = TRUE;
continue;
case 't': if (checkforcmd(&p, "tab", 3))
--- 2810,2827 ----
case 's': if (checkforcmd(&eap->cmd, "sandbox", 3))
{
! cmdmod.cmod_flags |= CMOD_SANDBOX;
continue;
}
if (!checkforcmd(&eap->cmd, "silent", 3))
break;
! cmdmod.cmod_flags |= CMOD_SILENT;
if (*eap->cmd == '!' && !VIM_ISWHITE(eap->cmd[-1]))
{
// ":silent!", but not "silent !cmd"
eap->cmd = skipwhite(eap->cmd + 1);
! cmdmod.cmod_flags |= CMOD_ERRSILENT;
}
continue;
case 't': if (checkforcmd(&p, "tab", 3))
***************
*** 2884,2895 ****
case 'u': if (!checkforcmd(&eap->cmd, "unsilent", 3))
break;
! if (!skip_only)
! {
! if (eap->save_msg_silent == -1)
! eap->save_msg_silent = msg_silent;
! msg_silent = 0;
! }
continue;
case 'v': if (checkforcmd(&eap->cmd, "vertical", 4))
--- 2853,2859 ----
case 'u': if (!checkforcmd(&eap->cmd, "unsilent", 3))
break;
! cmdmod.cmod_flags |= CMOD_UNSILENT;
continue;
case 'v': if (checkforcmd(&eap->cmd, "vertical", 4))
***************
*** 2899,2913 ****
}
if (!checkforcmd(&p, "verbose", 4))
break;
! if (!skip_only)
! {
! if (eap->verbose_save < 0)
! eap->verbose_save = p_verbose;
! if (vim_isdigit(*eap->cmd))
! p_verbose = atoi((char *)eap->cmd);
! else
! p_verbose = 1;
! }
eap->cmd = p;
continue;
}
--- 2863,2872 ----
}
if (!checkforcmd(&p, "verbose", 4))
break;
! if (vim_isdigit(*eap->cmd))
! cmdmod.cmod_verbose = atoi((char *)eap->cmd);
! else
! cmdmod.cmod_verbose = 1;
eap->cmd = p;
continue;
}
***************
*** 2918,2949 ****
}
/*
* Undo and free contents of "cmdmod".
*/
void
! undo_cmdmod(exarg_T *eap, int save_msg_scroll)
{
! if (eap->verbose_save >= 0)
! p_verbose = eap->verbose_save;
! if (cmdmod.save_ei != NULL)
{
// Restore 'eventignore' to the value before ":noautocmd".
! set_string_option_direct((char_u *)"ei", -1, cmdmod.save_ei,
OPT_FREE, SID_NONE);
! free_string_option(cmdmod.save_ei);
}
if (cmdmod.filter_regmatch.regprog != NULL)
vim_regfree(cmdmod.filter_regmatch.regprog);
! if (eap->save_msg_silent != -1)
{
// messages could be enabled for a serious error, need to check if the
// counters don't become negative
! if (!did_emsg || msg_silent > eap->save_msg_silent)
! msg_silent = eap->save_msg_silent;
! emsg_silent -= eap->did_esilent;
if (emsg_silent < 0)
emsg_silent = 0;
// Restore msg_scroll, it's set by file I/O commands, even when no
--- 2877,2965 ----
}
/*
+ * Apply the command modifiers. Saves current state in "cmdmod", call
+ * undo_cmdmod() later.
+ */
+ void
+ apply_cmdmod(cmdmod_T *cmod)
+ {
+ #ifdef HAVE_SANDBOX
+ if ((cmod->cmod_flags & CMOD_SANDBOX) && !cmod->cmod_did_sandbox)
+ {
+ ++sandbox;
+ cmod->cmod_did_sandbox = TRUE;
+ }
+ #endif
+ if (cmod->cmod_verbose > 0)
+ {
+ if (cmod->cmod_verbose_save == 0)
+ cmod->cmod_verbose_save = p_verbose + 1;
+ p_verbose = cmod->cmod_verbose;
+ }
+
+ if ((cmod->cmod_flags & (CMOD_SILENT | CMOD_UNSILENT))
+ && cmod->cmod_save_msg_silent == 0)
+ cmod->cmod_save_msg_silent = msg_silent + 1;
+ if (cmod->cmod_flags & CMOD_SILENT)
+ ++msg_silent;
+ if (cmod->cmod_flags & CMOD_UNSILENT)
+ msg_silent = 0;
+
+ if (cmod->cmod_flags & CMOD_ERRSILENT)
+ {
+ ++emsg_silent;
+ ++cmod->cmod_did_esilent;
+ }
+
+ if ((cmod->cmod_flags & CMOD_NOAUTOCMD) && cmdmod.cmod_save_ei == NULL)
+ {
+ // Set 'eventignore' to "all".
+ // First save the existing option value for restoring it later.
+ cmdmod.cmod_save_ei = vim_strsave(p_ei);
+ set_string_option_direct((char_u *)"ei", -1,
+ (char_u *)"all", OPT_FREE, SID_NONE);
+ }
+ }
+
+ /*
* Undo and free contents of "cmdmod".
*/
void
! undo_cmdmod(int save_msg_scroll)
{
! if (cmdmod.cmod_verbose_save > 0)
! {
! p_verbose = cmdmod.cmod_verbose_save - 1;
! cmdmod.cmod_verbose_save = 0;
! }
! #ifdef HAVE_SANDBOX
! if (cmdmod.cmod_did_sandbox)
! {
! --sandbox;
! cmdmod.cmod_did_sandbox = FALSE;
! }
! #endif
!
! if (cmdmod.cmod_save_ei != NULL)
{
// Restore 'eventignore' to the value before ":noautocmd".
! set_string_option_direct((char_u *)"ei", -1, cmdmod.cmod_save_ei,
OPT_FREE, SID_NONE);
! free_string_option(cmdmod.cmod_save_ei);
! cmdmod.cmod_save_ei = NULL;
}
if (cmdmod.filter_regmatch.regprog != NULL)
vim_regfree(cmdmod.filter_regmatch.regprog);
! if (cmdmod.cmod_save_msg_silent > 0)
{
// messages could be enabled for a serious error, need to check if the
// counters don't become negative
! if (!did_emsg || msg_silent > cmdmod.cmod_save_msg_silent - 1)
! msg_silent = cmdmod.cmod_save_msg_silent - 1;
! emsg_silent -= cmdmod.cmod_did_esilent;
if (emsg_silent < 0)
emsg_silent = 0;
// Restore msg_scroll, it's set by file I/O commands, even when no
***************
*** 2954,2959 ****
--- 2970,2978 ----
// somewhere in the line. Put it back in the first column.
if (redirecting())
msg_col = 0;
+
+ cmdmod.cmod_save_msg_silent = 0;
+ cmdmod.cmod_did_esilent = 0;
}
}
*** ../vim-8.2.1896/src/proto/
ex_docmd.pro 2020-09-14 16:37:30.906845912 +0200
--- src/proto/
ex_docmd.pro 2020-10-24 16:04:10.792027114 +0200
***************
*** 7,13 ****
char_u *getline_peek(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
char *ex_errmsg(char *msg, char_u *arg);
int parse_command_modifiers(exarg_T *eap, char **errormsg, int skip_only);
! void undo_cmdmod(exarg_T *eap, int save_msg_scroll);
int parse_cmd_address(exarg_T *eap, char **errormsg, int silent);
int checkforcmd(char_u **pp, char *cmd, int len);
char_u *skip_option_env_lead(char_u *start);
--- 7,14 ----
char_u *getline_peek(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
char *ex_errmsg(char *msg, char_u *arg);
int parse_command_modifiers(exarg_T *eap, char **errormsg, int skip_only);
! void apply_cmdmod(cmdmod_T *cmod);
! void undo_cmdmod(int save_msg_scroll);
int parse_cmd_address(exarg_T *eap, char **errormsg, int silent);
int checkforcmd(char_u **pp, char *cmd, int len);
char_u *skip_option_env_lead(char_u *start);
*** ../vim-8.2.1896/src/ex_cmds.h 2020-10-10 21:33:42.403033529 +0200
--- src/ex_cmds.h 2020-10-24 15:57:26.752808339 +0200
***************
*** 1884,1895 ****
#ifdef FEAT_EVAL
cstack_T *cstack; // condition stack for ":if" etc.
#endif
- long verbose_save; // saved value of p_verbose
- int save_msg_silent; // saved value of msg_silent
- int did_esilent; // how many times emsg_silent was incremented
- #ifdef HAVE_SANDBOX
- int did_sandbox; // when TRUE did ++sandbox
- #endif
};
#define FORCE_BIN 1 // ":edit ++bin file"
--- 1884,1889 ----
*** ../vim-8.2.1896/src/vim9compile.c 2020-10-23 18:02:28.707453763 +0200
--- src/vim9compile.c 2020-10-24 16:02:45.408209761 +0200
***************
*** 1831,1842 ****
isn_T *isn;
// TODO: use more modifiers in the command
! if (cmdmod.msg_silent || cmdmod.emsg_silent)
{
if ((isn = generate_instr(cctx, ISN_SILENT)) == NULL)
return FAIL;
! isn->isn_arg.number = cmdmod.emsg_silent;
! cctx->ctx_silent = cmdmod.emsg_silent ? 2 : 1;
}
return OK;
}
--- 1831,1842 ----
isn_T *isn;
// TODO: use more modifiers in the command
! if (cmdmod.cmod_flags & (CMOD_SILENT | CMOD_ERRSILENT))
{
if ((isn = generate_instr(cctx, ISN_SILENT)) == NULL)
return FAIL;
! isn->isn_arg.number = (cmdmod.cmod_flags & CMOD_ERRSILENT) != 0;
! cctx->ctx_silent = (cmdmod.cmod_flags & CMOD_ERRSILENT) ? 2 : 1;
}
return OK;
}
***************
*** 7187,7193 ****
}
generate_cmdmods(&cctx);
! undo_cmdmod(&ea, save_msg_scroll);
cmdmod = save_cmdmod;
// Skip ":call" to get to the function name.
--- 7187,7193 ----
}
generate_cmdmods(&cctx);
! undo_cmdmod(save_msg_scroll);
cmdmod = save_cmdmod;
// Skip ":call" to get to the function name.
*** ../vim-8.2.1896/src/version.c 2020-10-24 13:30:46.280240528 +0200
--- src/version.c 2020-10-24 17:17:52.263945615 +0200
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 1897,
/**/
--
hundred-and-one symptoms of being an internet addict:
123. You ask the car dealer to install an extra cigarette lighter
on your new car to power your notebook.
/// Bram Moolenaar -- Br...@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 ///