]> granicus.if.org Git - vim/commitdiff
patch 8.2.3228: cannot use a simple block for the :command argument v8.2.3228
authorBram Moolenaar <Bram@vim.org>
Tue, 27 Jul 2021 19:17:32 +0000 (21:17 +0200)
committerBram Moolenaar <Bram@vim.org>
Tue, 27 Jul 2021 19:17:32 +0000 (21:17 +0200)
Problem:    Cannot use a simple block for the :command argument. (Maarten
            Tournoij)
Solution:   Recognize a simple {} block. (issue #8623)

runtime/doc/map.txt
src/misc2.c
src/proto/misc2.pro
src/testdir/test_usercommands.vim
src/usercmd.c
src/version.c

index 970bbc923e57d0a9e7814dbe1903fbf48448e54f..8d5caf43a9f79a0dc99f6d79f6b28aa3d4cbbbfc 100644 (file)
@@ -1572,6 +1572,16 @@ feature.  Use the full name for new scripts.
 
 Replacement text ~
 
+The {repl} argument is normally one long string, possibly with "|" separated
+commands.  A special case is when the argument is "{", then the following
+lines, up to a line starting with "}" are used and |Vim9| syntax applies.
+Example: >
+       :command MyCommand {
+               echo 'hello'
+               g:calledMyCommand = true
+           }
+No nesting is supported.
+
 The replacement text {repl} for a user defined command is scanned for special
 escape sequences, using <...> notation.  Escape sequences are replaced with
 values from the entered command line, and all other text is copied unchanged.
index 8e99b01a5e08c4a025c35b3a5bde0ae3b1aca25b..bc984b219839d7536309404e96f38d8f227046d5 100644 (file)
@@ -1488,7 +1488,6 @@ ga_grow_inner(garray_T *gap, int n)
     return OK;
 }
 
-#if defined(FEAT_EVAL) || defined(FEAT_SEARCHPATH) || defined(PROTO)
 /*
  * For a growing array that contains a list of strings: concatenate all the
  * strings with a separating "sep".
@@ -1524,27 +1523,27 @@ ga_concat_strings(garray_T *gap, char *sep)
     }
     return s;
 }
-#endif
 
-#if defined(FEAT_VIMINFO) || defined(FEAT_EVAL) || defined(PROTO)
 /*
  * Make a copy of string "p" and add it to "gap".
- * When out of memory nothing changes.
+ * When out of memory nothing changes and FAIL is returned.
  */
-    void
+    int
 ga_add_string(garray_T *gap, char_u *p)
 {
     char_u *cp = vim_strsave(p);
 
-    if (cp != NULL)
+    if (cp == NULL)
+       return FAIL;
+
+    if (ga_grow(gap, 1) == FAIL)
     {
-       if (ga_grow(gap, 1) == OK)
-           ((char_u **)(gap->ga_data))[gap->ga_len++] = cp;
-       else
-           vim_free(cp);
+       vim_free(cp);
+       return FAIL;
     }
+    ((char_u **)(gap->ga_data))[gap->ga_len++] = cp;
+    return OK;
 }
-#endif
 
 /*
  * Concatenate a string to a growarray which contains bytes.
index 5f7d70927b3ef9e5305bed03737689f2c7f09f2d..5ecd5958fdda2dcefcab7bd07e518503af69d046 100644 (file)
@@ -43,7 +43,7 @@ void ga_init2(garray_T *gap, int itemsize, int growsize);
 int ga_grow(garray_T *gap, int n);
 int ga_grow_inner(garray_T *gap, int n);
 char_u *ga_concat_strings(garray_T *gap, char *sep);
-void ga_add_string(garray_T *gap, char_u *p);
+int ga_add_string(garray_T *gap, char_u *p);
 void ga_concat(garray_T *gap, char_u *s);
 void ga_append(garray_T *gap, int c);
 void append_ga_line(garray_T *gap);
index f0f056f88ce2e4e66733b3223bad9bddb1d2fd45..df8893709df28543d07b279156e6741e48d1bfcd 100644 (file)
@@ -622,4 +622,22 @@ func Test_usercmd_custom()
   delfunc T2
 endfunc
 
+func Test_usercmd_with_block()
+  command DoSomething {
+        g:didit = 'yes'
+        g:didmore = 'more'
+      }
+  DoSomething
+  call assert_equal('yes', g:didit)
+  call assert_equal('more', g:didmore)
+  unlet g:didit
+  unlet g:didmore
+
+  let lines =<< trim END
+      command DoesNotEnd {
+         echo 'hello'
+  END
+  call CheckScriptFailure(lines, 'E1026:')
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index 42b9014f38e2605757e5add0f51323934f469058..09e7b26b3c4db48844f19c305b24417392eb3dd2 100644 (file)
@@ -115,6 +115,7 @@ static struct
 };
 
 #define UC_BUFFER      1       // -buffer: local to current buffer
+#define UC_VIM9                2       // {} argument: Vim9 syntax.
 
 /*
  * Search for a user command that matches "eap->cmd".
@@ -872,10 +873,10 @@ uc_add_command(
     replace_termcodes(rep, &rep_buf, 0, NULL);
     if (rep_buf == NULL)
     {
-       // Can't replace termcodes - try using the string as is
+       // can't replace termcodes - try using the string as is
        rep_buf = vim_strsave(rep);
 
-       // Give up if out of memory
+       // give up if out of memory
        if (rep_buf == NULL)
            return FAIL;
     }
@@ -955,6 +956,8 @@ uc_add_command(
     cmd->uc_def = def;
     cmd->uc_compl = compl;
     cmd->uc_script_ctx = current_sctx;
+    if (flags & UC_VIM9)
+       cmd->uc_script_ctx.sc_version = SCRIPT_VERSION_VIM9;
 #ifdef FEAT_EVAL
     cmd->uc_script_ctx.sc_lnum += SOURCING_LNUM;
     cmd->uc_compl_arg = compl_arg;
@@ -1037,8 +1040,46 @@ ex_command(exarg_T *eap)
                       (char_u *)_(e_complete_used_without_nargs), TRUE, TRUE);
     }
     else
+    {
+       char_u *tofree = NULL;
+
+       if (*p == '{' && ends_excmd2(eap->arg, skipwhite(p + 1))
+                                                      && eap->getline != NULL)
+       {
+           garray_T    ga;
+           char_u      *line = NULL;
+
+           ga_init2(&ga, sizeof(char_u *), 10);
+           if (ga_add_string(&ga, p) == FAIL)
+               return;
+
+           // Read lines between '{' and '}'.  Does not support nesting or
+           // here-doc constructs.
+           //
+           for (;;)
+           {
+               vim_free(line);
+               if ((line = eap->getline(':', eap->cookie,
+                                          0, GETLINE_CONCAT_CONTBAR)) == NULL)
+               {
+                   emsg(_(e_missing_rcurly));
+                   break;
+               }
+               if (ga_add_string(&ga, line) == FAIL)
+                   break;
+               if (*skipwhite(line) == '}')
+                   break;
+           }
+           vim_free(line);
+           p = tofree = ga_concat_strings(&ga, "\n");
+           ga_clear_strings(&ga);
+           flags |= UC_VIM9;
+       }
+
        uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg,
                                                  addr_type_arg, eap->forceit);
+       vim_free(tofree);
+    }
 }
 
 /*
index cdf5d4e4e96f2b6ff9a681031a90982b90b6beeb..e38274ef311e5a9116fe3addb815c888685d4750 100644 (file)
@@ -755,6 +755,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3228,
 /**/
     3227,
 /**/