# HG changeset patch # User Bram Moolenaar # Date 1603469703 -7200 # Node ID dda110a14be40d774ceeca34b089fd7dfc5325b5 # Parent 3b5c9b442a730031e1dbe4cb013d151299de53b1 patch 8.2.1894: Vim9: command modifiers are not supported Commit: https://github.com/vim/vim/commit/f4c6e1e75c2a7f2ca3a7f4529e7da31dc98557e9 Author: Bram Moolenaar Date: Fri Oct 23 18:02:32 2020 +0200 patch 8.2.1894: Vim9: command modifiers are not supported Problem: Vim9: command modifiers are not supported. Solution: Support "silent" and "silent!". diff --git a/src/evalvars.c b/src/evalvars.c --- a/src/evalvars.c +++ b/src/evalvars.c @@ -3577,9 +3577,11 @@ var_redir_start(char_u *name, int append tv.v_type = VAR_STRING; tv.vval.v_string = (char_u *)""; if (append) - set_var_lval(redir_lval, redir_endp, &tv, TRUE, 0, (char_u *)"."); + set_var_lval(redir_lval, redir_endp, &tv, TRUE, + ASSIGN_NO_DECL, (char_u *)"."); else - set_var_lval(redir_lval, redir_endp, &tv, TRUE, 0, (char_u *)"="); + set_var_lval(redir_lval, redir_endp, &tv, TRUE, + ASSIGN_NO_DECL, (char_u *)"="); clear_lval(redir_lval); if (called_emsg > called_emsg_before) { diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -643,6 +643,8 @@ typedef struct 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 diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -401,5 +401,17 @@ def Test_f_args() CheckScriptSuccess(lines) enddef +def Test_modifier_silent() + echomsg 'last one' + silent echomsg "text" + redir => g:testmsg + :1messages + redir END + assert_equal("\nlast one", g:testmsg) + unlet g:testmsg + + silent! echoerr "error" +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -1617,4 +1617,28 @@ def Test_shuffle() res) enddef + +def s:SilentMessage() + silent echomsg "text" + silent! echoerr "error" +enddef + +def Test_silent() + var res = execute('disass s:SilentMessage') + assert_match('\d*_SilentMessage\_s*' .. + 'silent echomsg "text"\_s*' .. + '\d SILENT\_s*' .. + '\d PUSHS "text"\_s*' .. + '\d ECHOMSG 1\_s*' .. + '\d UNSILENT\_s*' .. + 'silent! echoerr "error"\_s*' .. + '\d SILENT!\_s*' .. + '\d PUSHS "error"\_s*' .. + '\d ECHOERR 1\_s*' .. + '\d UNSILENT!\_s*' .. + '\d PUSHNR 0\_s*' .. + '\d RETURN', + res) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1894, +/**/ 1893, /**/ 1892, diff --git a/src/vim9.h b/src/vim9.h --- a/src/vim9.h +++ b/src/vim9.h @@ -142,6 +142,9 @@ typedef enum { ISN_PUT, // ":put", uses isn_arg.put + ISN_SILENT, // set msg_silent or emsg_silent if arg_number is non-zero + ISN_UNSILENT, // undo ISN_SILENT + ISN_SHUFFLE, // move item on stack up or down ISN_DROP // pop stack and discard value } isntype_T; diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -141,6 +141,8 @@ struct cctx_S { garray_T ctx_type_stack; // type of each item on the stack garray_T *ctx_type_list; // list of pointers to allocated types + + int ctx_silent; // set when ISN_SILENT was generated }; static void delete_def_function_contents(dfunc_T *dfunc); @@ -1821,6 +1823,40 @@ generate_EXECCONCAT(cctx_T *cctx, int co } /* + * Generate any instructions for side effects of "cmdmod". + */ + static int +generate_cmdmods(cctx_T *cctx) +{ + 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; +} + + static int +generate_restore_cmdmods(cctx_T *cctx) +{ + isn_T *isn; + + if (cctx->ctx_silent > 0) + { + if ((isn = generate_instr(cctx, ISN_UNSILENT)) == NULL) + return FAIL; + isn->isn_arg.number = cctx->ctx_silent == 2; + cctx->ctx_silent = 0; + } + return OK; +} + +/* * Reserve space for a local variable. * Return the variable or NULL if it failed. */ @@ -7149,7 +7185,8 @@ compile_def_function(ufunc_T *ufunc, int line = (char_u *)""; continue; } - // TODO: use modifiers in the command + generate_cmdmods(&cctx); + undo_cmdmod(&ea, save_msg_scroll); cmdmod = save_cmdmod; @@ -7461,6 +7498,9 @@ nextline: goto erret; line = skipwhite(line); + // Undo any command modifiers. + generate_restore_cmdmods(&cctx); + if (cctx.ctx_type_stack.ga_len < 0) { iemsg("Type stack underflow"); @@ -7767,6 +7807,7 @@ delete_instr(isn_T *isn) case ISN_PUT: case ISN_RETURN: case ISN_SHUFFLE: + case ISN_SILENT: case ISN_SLICE: case ISN_STORE: case ISN_STOREDICT: @@ -7780,6 +7821,7 @@ delete_instr(isn_T *isn) case ISN_STRSLICE: case ISN_THROW: case ISN_TRY: + case ISN_UNSILENT: // nothing allocated break; } diff --git a/src/vim9execute.c b/src/vim9execute.c --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -832,6 +832,8 @@ call_def_function( int save_suppress_errthrow = suppress_errthrow; msglist_T **saved_msg_list = NULL; msglist_T *private_msg_list = NULL; + int save_msg_silent = -1; + int save_emsg_silent = -1; // Get pointer to item in the stack. #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) @@ -2814,6 +2816,24 @@ call_def_function( } break; + case ISN_SILENT: + if (save_msg_silent == -1) + save_msg_silent = msg_silent; + ++msg_silent; + if (iptr->isn_arg.number) + { + if (save_emsg_silent == -1) + save_emsg_silent = emsg_silent; + ++emsg_silent; + } + break; + + case ISN_UNSILENT: + --msg_silent; + if (iptr->isn_arg.number) + --emsg_silent; + break; + case ISN_SHUFFLE: { typval_T tmp_tv; @@ -2885,6 +2905,11 @@ failed: } msg_list = saved_msg_list; + if (save_msg_silent != -1) + msg_silent = save_msg_silent; + if (save_emsg_silent != -1) + emsg_silent = save_emsg_silent; + failed_early: // Free all local variables, but not arguments. for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx) @@ -3502,6 +3527,11 @@ ex_disassemble(exarg_T *eap) (long)iptr->isn_arg.put.put_lnum); break; + case ISN_SILENT: smsg("%4d SILENT%s", current, + iptr->isn_arg.number ? "!" : ""); break; + case ISN_UNSILENT: smsg("%4d UNSILENT%s", current, + iptr->isn_arg.number ? "!" : ""); break; + case ISN_SHUFFLE: smsg("%4d SHUFFLE %d up %d", current, iptr->isn_arg.shuffle.shfl_item, iptr->isn_arg.shuffle.shfl_up);