]> granicus.if.org Git - vim/commitdiff
patch 8.1.0619: :echomsg and :echoerr do not handle List and Dict v8.1.0619
authorBram Moolenaar <Bram@vim.org>
Sat, 22 Dec 2018 12:28:07 +0000 (13:28 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 22 Dec 2018 12:28:07 +0000 (13:28 +0100)
Problem:    :echomsg and :echoerr do not handle List and Dict like :echo does.
            (Daniel Hahler)
Solution:   Be more tolerant about the expression result type.

runtime/doc/eval.txt
src/eval.c
src/evalfunc.c
src/message.c
src/proto/eval.pro
src/proto/evalfunc.pro
src/testdir/test_messages.vim
src/version.c

index f76af3848a289247fcde27e8befe339dcd18eaec..2bc27a62956f47f869fff85a1535d46929a93d4f 100644 (file)
@@ -9233,7 +9233,8 @@ test_ignore_error({expr})                  *test_ignore_error()*
                error with try/catch cannot be used (because it skips over
                following code).
                {expr} is used literally, not as a pattern.
-               There is currently no way to revert this.
+               When the {expr} is the string "RESET" then the list of ignored
+               errors is made empty.
 
 test_null_channel()                                    *test_null_channel()*
                Return a Channel that is null. Only useful for testing.
@@ -10999,8 +11000,8 @@ This does NOT work: >
                        The parsing works slightly different from |:echo|,
                        more like |:execute|.  All the expressions are first
                        evaluated and concatenated before echoing anything.
-                       The expressions must evaluate to a Number or String, a
-                       Dictionary or List causes an error.
+                       If expressions does not evaluate to a Number or
+                       String, string() is used to turn it into a string.
                        Uses the highlighting set by the |:echohl| command.
                        Example: >
                :echomsg "It's a Zizzer Zazzer Zuzz, as you can plainly see."
@@ -11011,7 +11012,7 @@ This does NOT work: >
                        message in the |message-history|.  When used in a
                        script or function the line number will be added.
                        Spaces are placed between the arguments as with the
-                       :echo command.  When used inside a try conditional,
+                       |:echomsg| command.  When used inside a try conditional,
                        the message is raised as an error exception instead
                        (see |try-echoerr|).
                        Example: >
index 1d14e1b0e51e5009466f14bf288f8271abb6c854..b6463d2e70c439d79f8bf446956669b90400625f 100644 (file)
@@ -7162,6 +7162,30 @@ tv_get_string_buf_chk(typval_T *varp, char_u *buf)
     return NULL;
 }
 
+/*
+ * Turn a typeval into a string.  Similar to tv_get_string_buf() but uses
+ * string() on Dict, List, etc.
+ */
+    char_u *
+tv_stringify(typval_T *varp, char_u *buf)
+{
+    if (varp->v_type == VAR_LIST
+           || varp->v_type == VAR_DICT
+           || varp->v_type == VAR_FUNC
+           || varp->v_type == VAR_PARTIAL
+           || varp->v_type == VAR_FLOAT)
+    {
+       typval_T tmp;
+
+       f_string(varp, &tmp);
+       tv_get_string_buf(&tmp, buf);
+       clear_tv(varp);
+       *varp = tmp;
+       return tmp.vval.v_string;
+    }
+    return tv_get_string_buf(varp, buf);
+}
+
 /*
  * Find variable "name" in the list of variables.
  * Return a pointer to it if found, NULL if not found.
@@ -8142,7 +8166,12 @@ ex_execute(exarg_T *eap)
 
        if (!eap->skip)
        {
-           p = tv_get_string(&rettv);
+           char_u   buf[NUMBUFLEN];
+
+           if (eap->cmdidx == CMD_execute)
+               p = tv_get_string_buf(&rettv, buf);
+           else
+               p = tv_stringify(&rettv, buf);
            len = (int)STRLEN(p);
            if (ga_grow(&ga, len + 2) == FAIL)
            {
index cbe2a4ebb5b6ca9468cc29266578cf958271d43f..bd2acef7fdd5f296593843ebc56d3867721e3ea7 100644 (file)
@@ -396,7 +396,6 @@ static void f_strftime(typval_T *argvars, typval_T *rettv);
 #endif
 static void f_strgetchar(typval_T *argvars, typval_T *rettv);
 static void f_stridx(typval_T *argvars, typval_T *rettv);
-static void f_string(typval_T *argvars, typval_T *rettv);
 static void f_strlen(typval_T *argvars, typval_T *rettv);
 static void f_strcharpart(typval_T *argvars, typval_T *rettv);
 static void f_strpart(typval_T *argvars, typval_T *rettv);
@@ -12475,7 +12474,7 @@ f_stridx(typval_T *argvars, typval_T *rettv)
 /*
  * "string()" function
  */
-    static void
+    void
 f_string(typval_T *argvars, typval_T *rettv)
 {
     char_u     *tofree;
index f191c78a27d353023be7d8a4f749d7a0bf64cffa..1c9fbe513c19ec6cb080a9a9b48f927de8ee013a 100644 (file)
@@ -553,7 +553,10 @@ ignore_error_for_testing(char_u *error)
     if (ignore_error_list.ga_itemsize == 0)
        ga_init2(&ignore_error_list, sizeof(char_u *), 1);
 
-    ga_add_string(&ignore_error_list, error);
+    if (STRCMP("RESET", error) == 0)
+       ga_clear_strings(&ignore_error_list);
+    else
+       ga_add_string(&ignore_error_list, error);
 }
 
     static int
index bc6808c746196df3d07a1248110f762077c992ea..7d73f6c28cb093f199d5ca150b64fb68bc102456 100644 (file)
@@ -89,6 +89,7 @@ char_u *tv_get_string(typval_T *varp);
 char_u *tv_get_string_buf(typval_T *varp, char_u *buf);
 char_u *tv_get_string_chk(typval_T *varp);
 char_u *tv_get_string_buf_chk(typval_T *varp, char_u *buf);
+char_u *tv_stringify(typval_T *varp, char_u *buf);
 dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload);
 dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload);
 hashtab_T *find_var_ht(char_u *name, char_u **varname);
index c79b59c0d935fba5db10f977068e5819beb0d269..09861628b5c042088801317a4c2a22e250328c65 100644 (file)
@@ -9,6 +9,7 @@ void execute_redir_str(char_u *value, int value_len);
 void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
 float_T vim_round(float_T f);
 long do_searchpair(char_u *spat, char_u *mpat, char_u *epat, int dir, typval_T *skip, int flags, pos_T *match_pos, linenr_T lnum_stop, long time_limit);
+void f_string(typval_T *argvars, typval_T *rettv);
 char_u *get_callback(typval_T *arg, partial_T **pp);
 void free_callback(char_u *callback, partial_T *partial);
 /* vim: set ft=c : */
index de14b81f9a5812becce8c6e48801b18f4ebfd31a..0a7f3f59a209e2ddf0fba0521aa1314108b56a6b 100644 (file)
@@ -1,4 +1,4 @@
-" Tests for :messages
+" Tests for :messages, :echomsg, :echoerr
 
 function Test_messages()
   let oldmore = &more
@@ -64,3 +64,31 @@ func Test_message_completion()
   call feedkeys(":message \<C-A>\<C-B>\"\<CR>", 'tx')
   call assert_equal('"message clear', @:)
 endfunc
+
+func Test_echomsg()
+  call assert_equal("\nhello", execute(':echomsg "hello"'))
+  call assert_equal("\n", execute(':echomsg ""'))
+  call assert_equal("\n12345", execute(':echomsg 12345'))
+  call assert_equal("\n[]", execute(':echomsg []'))
+  call assert_equal("\n[1, 2, 3]", execute(':echomsg [1, 2, 3]'))
+  call assert_equal("\n{}", execute(':echomsg {}'))
+  call assert_equal("\n{'a': 1, 'b': 2}", execute(':echomsg {"a": 1, "b": 2}'))
+  if has('float')
+    call assert_equal("\n1.23", execute(':echomsg 1.23'))
+  endif
+  call assert_match("function('<lambda>\\d*')", execute(':echomsg {-> 1234}'))
+endfunc
+
+func Test_echoerr()
+  call test_ignore_error('IgNoRe')
+  call assert_equal("\nIgNoRe hello", execute(':echoerr "IgNoRe hello"'))
+  call assert_equal("\n12345 IgNoRe", execute(':echoerr 12345 "IgNoRe"'))
+  call assert_equal("\n[1, 2, 'IgNoRe']", execute(':echoerr [1, 2, "IgNoRe"]'))
+  call assert_equal("\n{'IgNoRe': 2, 'a': 1}", execute(':echoerr {"a": 1, "IgNoRe": 2}'))
+  if has('float')
+    call assert_equal("\n1.23 IgNoRe", execute(':echoerr 1.23 "IgNoRe"'))
+  endif
+  call test_ignore_error('<lambda>')
+  call assert_match("function('<lambda>\\d*')", execute(':echoerr {-> 1234}'))
+  call test_ignore_error('RESET')
+endfunc
index 1612f9dd1a62a98fab92bfb965d4d00fa90314c0..b1a28c1faa00eb2e97740766f5bfc5d7e7fda8b6 100644 (file)
@@ -799,6 +799,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    619,
 /**/
     618,
 /**/