To: vim_dev@googlegroups.com Subject: Patch 8.2.1897 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 -- 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 ///