]> granicus.if.org Git - vim/commitdiff
patch 8.2.1894: Vim9: command modifiers are not supported v8.2.1894
authorBram Moolenaar <Bram@vim.org>
Fri, 23 Oct 2020 16:02:32 +0000 (18:02 +0200)
committerBram Moolenaar <Bram@vim.org>
Fri, 23 Oct 2020 16:02:32 +0000 (18:02 +0200)
Problem:    Vim9: command modifiers are not supported.
Solution:   Support "silent" and "silent!".

src/evalvars.c
src/structs.h
src/testdir/test_vim9_cmd.vim
src/testdir/test_vim9_disassemble.vim
src/version.c
src/vim9.h
src/vim9compile.c
src/vim9execute.c

index b3ad2c99c8818cda6bc2cd4548dad35aea6ba6db..1f418ae22848af2a056a5cb523600bb34fd9d786 100644 (file)
@@ -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)
     {
index eb86e484ed3ef834cf2042add93b5108e4609480..f01598e7adfafdce7801ed51b5b1001954577ea4 100644 (file)
@@ -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
index 296aa55e6df80dab5128005087e993216c5ae958..710cd2f8dcb606952b9155ec30effee457f34f10 100644 (file)
@@ -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
index 97797bc03add993daec3dd91151b45300c7f99e7..eadac2763541ae8db032f4efba3b74b41a6325a9 100644 (file)
@@ -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('<SNR>\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
index fa1e0fd3a12b2b87dc3a38063bfe9981c6d6dfe3..217c61548e9720e9e01ee68bb2191d049cdb4ee0 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1894,
 /**/
     1893,
 /**/
index 68b9bfab3897168a0b18dfbe7cc24dcbfd1dcc83..8056c603f3c5b15515d1555526ee25f346fab51e 100644 (file)
@@ -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;
index 45c35b2e4b29659ab5646bd68b5c817956dfb549..421957708632d88446ba60f1966902b3dd8a1e2c 100644 (file)
@@ -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);
@@ -1820,6 +1822,40 @@ generate_EXECCONCAT(cctx_T *cctx, int count)
     return OK;
 }
 
+/*
+ * 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 set_return_type, cctx_T *outer_cctx)
            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;
     }
index 115212fdcee7127e19c8bc1f727a62d9f30f07c1..759154e01ace6cc11113b9595fd29cd79ef9c9b6 100644 (file)
@@ -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);