]> granicus.if.org Git - vim/commitdiff
patch 8.2.2435: setline() gives an error for some types v8.2.2435
authorBram Moolenaar <Bram@vim.org>
Sun, 31 Jan 2021 12:08:38 +0000 (13:08 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 31 Jan 2021 12:08:38 +0000 (13:08 +0100)
Problem:    setline() gives an error for some types.
Solution:   Allow any type, convert each item to a string.

runtime/doc/eval.txt
src/debugger.c
src/evalbuffer.c
src/proto/typval.pro
src/testdir/test_bufline.vim
src/testdir/test_vim9_builtin.vim
src/typval.c
src/version.c
src/vim9execute.c

index edf5fc8cc3b4ad01888e0bacd37aa44503c3c265..1c4f46e6bb9a906869a7b9dd7e54391a7a28cda0 100644 (file)
@@ -1,4 +1,4 @@
-*eval.txt*     For Vim version 8.2.  Last change: 2021 Jan 22
+*eval.txt*     For Vim version 8.2.  Last change: 2021 Jan 31
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -293,13 +293,13 @@ is not available it returns zero or the default value you specify: >
 
 
 List concatenation ~
-
+                                                       *list-concatenation*
 Two lists can be concatenated with the "+" operator: >
        :let longlist = mylist + [5, 6]
        :let mylist += [7, 8]
 
-To prepend or append an item turn the item into a list by putting [] around
-it.  To change a list in-place see |list-modification| below.
+To prepend or append an item, turn the item into a list by putting [] around
+it.  To change a list in-place, refer to |list-modification| below.
 
 
 Sublist ~
@@ -3133,6 +3133,7 @@ append({lnum}, {text})                                    *append()*
                text line below line {lnum} in the current buffer.
                Otherwise append {text} as one text line below line {lnum} in
                the current buffer.
+               Any type of item is accepted and converted to a String.
                {lnum} can be zero to insert a line before the first one.
                Returns 1 for failure ({lnum} out of range or out of memory),
                0 for success.  Example: >
@@ -9409,6 +9410,8 @@ setline({lnum}, {text})                                   *setline()*
                {lnum} is used like with |getline()|.
                When {lnum} is just below the last line the {text} will be
                added below the last line.
+               {text} can be any type or a List of any type, each item is
+               converted to a String.
 
                If this succeeds, FALSE is returned.  If this fails (most likely
                because {lnum} is invalid) TRUE is returned.
index 4e8a1731861642ffaab3e2a7a43eca770ac22925..6f52e984d10de89235255b24bb2fb5bcc2ab52e0 100644 (file)
@@ -940,9 +940,9 @@ debuggy_find(
            {
                if (bp->dbg_val == NULL)
                {
-                   debug_oldval = typval_tostring(NULL);
+                   debug_oldval = typval_tostring(NULL, TRUE);
                    bp->dbg_val = tv;
-                   debug_newval = typval_tostring(bp->dbg_val);
+                   debug_newval = typval_tostring(bp->dbg_val, TRUE);
                    line = TRUE;
                }
                else
@@ -953,11 +953,11 @@ debuggy_find(
                        typval_T *v;
 
                        line = TRUE;
-                       debug_oldval = typval_tostring(bp->dbg_val);
+                       debug_oldval = typval_tostring(bp->dbg_val, TRUE);
                        // Need to evaluate again, typval_compare() overwrites
                        // "tv".
                        v = eval_expr(bp->dbg_name, NULL);
-                       debug_newval = typval_tostring(v);
+                       debug_newval = typval_tostring(v, TRUE);
                        free_tv(bp->dbg_val);
                        bp->dbg_val = v;
                    }
@@ -966,8 +966,8 @@ debuggy_find(
            }
            else if (bp->dbg_val != NULL)
            {
-               debug_oldval = typval_tostring(bp->dbg_val);
-               debug_newval = typval_tostring(NULL);
+               debug_oldval = typval_tostring(bp->dbg_val, TRUE);
+               debug_newval = typval_tostring(NULL, TRUE);
                free_tv(bp->dbg_val);
                bp->dbg_val = NULL;
                line = TRUE;
index 3fed3893e986121aec616121fcb970942d48353b..2ba2f679a5c7b4d58da10ceb5d3c33642621138a 100644 (file)
@@ -128,7 +128,8 @@ find_win_for_curbuf(void)
 }
 
 /*
- * Set line or list of lines in buffer "buf".
+ * Set line or list of lines in buffer "buf" to "lines".
+ * Any type is allowed and converted to a string.
  */
     static void
 set_buffer_lines(
@@ -187,7 +188,7 @@ set_buffer_lines(
        li = l->lv_first;
     }
     else
-       line = tv_get_string_chk(lines);
+       line = typval_tostring(lines, FALSE);
 
     // default result is zero == OK
     for (;;)
@@ -197,7 +198,8 @@ set_buffer_lines(
            // list argument, get next string
            if (li == NULL)
                break;
-           line = tv_get_string_chk(&li->li_tv);
+           vim_free(line);
+           line = typval_tostring(&li->li_tv, FALSE);
            li = li->li_next;
        }
 
@@ -238,6 +240,7 @@ set_buffer_lines(
            break;
        ++lnum;
     }
+    vim_free(line);
 
     if (added > 0)
     {
index 93eb64f4d304dcf4e77e6500dbf360c13414a9ee..ca4fe96723569351dd4b60065f4b0d88f03aa523 100644 (file)
@@ -21,7 +21,7 @@ char_u *tv_stringify(typval_T *varp, char_u *buf);
 int tv_check_lock(typval_T *tv, char_u *name, int use_gettext);
 void copy_tv(typval_T *from, typval_T *to);
 int typval_compare(typval_T *typ1, typval_T *typ2, exprtype_T type, int ic);
-char_u *typval_tostring(typval_T *arg);
+char_u *typval_tostring(typval_T *arg, int quotes);
 int tv_islocked(typval_T *tv);
 int tv_equal(typval_T *tv1, typval_T *tv2, int ic, int recursive);
 int eval_option(char_u **arg, typval_T *rettv, int evaluate);
index 0f5bac8733d96f82448ef84abc2725734ef04cfb..b2de198ef0eab51936af346ee293edbcb718631f 100644 (file)
@@ -5,6 +5,7 @@ source screendump.vim
 source check.vim
 
 func Test_setbufline_getbufline()
+  " similar to Test_set_get_bufline()
   new
   let b = bufnr('%')
   hide
@@ -38,6 +39,12 @@ func Test_setbufline_getbufline()
   call assert_equal(['e'], getbufline(b, 5))
   call assert_equal([], getbufline(b, 6))
   call assert_equal([], getbufline(b, 2, 1))
+
+  call setbufline(b, 2, [function('eval'), #{key: 123}, test_null_job()])
+  call assert_equal(["function('eval')",
+                  \ "{'key': 123}",
+                  \ "no process"],
+                  \ getbufline(b, 2, 4))
   exe "bwipe! " . b
 endfunc
 
index 292910016230e6f4f74af906d864ac6149340acc..d9275e617bd04a7366cbe2e91b372b1b2f1a1778 100644 (file)
@@ -767,6 +767,54 @@ def Test_searchcount()
   bwipe!
 enddef
 
+def Test_set_get_bufline()
+  # similar to Test_setbufline_getbufline()
+  var lines =<< trim END
+      new
+      var b = bufnr('%')
+      hide
+      assert_equal(0, setbufline(b, 1, ['foo', 'bar']))
+      assert_equal(['foo'], getbufline(b, 1))
+      assert_equal(['bar'], getbufline(b, '$'))
+      assert_equal(['foo', 'bar'], getbufline(b, 1, 2))
+      exe "bd!" b
+      assert_equal([], getbufline(b, 1, 2))
+
+      split Xtest
+      setline(1, ['a', 'b', 'c'])
+      b = bufnr('%')
+      wincmd w
+
+      assert_equal(1, setbufline(b, 5, 'x'))
+      assert_equal(1, setbufline(b, 5, ['x']))
+      assert_equal(1, setbufline(b, 5, []))
+      assert_equal(1, setbufline(b, 5, test_null_list()))
+
+      assert_equal(1, 'x'->setbufline(bufnr('$') + 1, 1))
+      assert_equal(1, ['x']->setbufline(bufnr('$') + 1, 1))
+      assert_equal(1, []->setbufline(bufnr('$') + 1, 1))
+      assert_equal(1, test_null_list()->setbufline(bufnr('$') + 1, 1))
+
+      assert_equal(['a', 'b', 'c'], getbufline(b, 1, '$'))
+
+      assert_equal(0, setbufline(b, 4, ['d', 'e']))
+      assert_equal(['c'], b->getbufline(3))
+      assert_equal(['d'], getbufline(b, 4))
+      assert_equal(['e'], getbufline(b, 5))
+      assert_equal([], getbufline(b, 6))
+      assert_equal([], getbufline(b, 2, 1))
+
+      setbufline(b, 2, [function('eval'), {key: 123}, test_null_job()])
+      assert_equal(["function('eval')",
+                      "{'key': 123}",
+                      "no process"],
+                      getbufline(b, 2, 4))
+
+      exe 'bwipe! ' .. b
+  END
+  CheckDefAndScriptSuccess(lines)
+enddef
+
 def Test_searchdecl()
   searchdecl('blah', true, true)->assert_equal(1)
 enddef
index b3325b663aaa1bb27bc7f028fcdb4a5af465e231..65e07b3f79fc1117f20f8e7d691dfdd40d5ff144 100644 (file)
@@ -927,8 +927,13 @@ typval_compare(
     return OK;
 }
 
+/*
+ * Convert any type to a string, never give an error.
+ * When "quotes" is TRUE add quotes to a string.
+ * Returns an allocated string.
+ */
     char_u *
-typval_tostring(typval_T *arg)
+typval_tostring(typval_T *arg, int quotes)
 {
     char_u     *tofree;
     char_u     numbuf[NUMBUFLEN];
@@ -936,10 +941,18 @@ typval_tostring(typval_T *arg)
 
     if (arg == NULL)
        return vim_strsave((char_u *)"(does not exist)");
-    ret = tv2string(arg, &tofree, numbuf, 0);
-    // Make a copy if we have a value but it's not in allocated memory.
-    if (ret != NULL && tofree == NULL)
-       ret = vim_strsave(ret);
+    if (!quotes && arg->v_type == VAR_STRING)
+    {
+       ret = vim_strsave(arg->vval.v_string == NULL ? (char_u *)""
+                                                        : arg->vval.v_string);
+    }
+    else
+    {
+       ret = tv2string(arg, &tofree, numbuf, 0);
+       // Make a copy if we have a value but it's not in allocated memory.
+       if (ret != NULL && tofree == NULL)
+           ret = vim_strsave(ret);
+    }
     return ret;
 }
 
index 8159289cb26e4746c9ffdfdd1bfb9a739369a988..1347decd54d2b4b0145f9c6c50e56d8b3a124934 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2435,
 /**/
     2434,
 /**/
index bcdc5d190a8ba877fc1880439fcb6f6cf4f55e6a..8a5708cc35a79837d21229b6e5630bb7c8d4140f 100644 (file)
@@ -879,7 +879,7 @@ do_2string(typval_T *tv, int is_2string_any)
                                return FAIL;
            }
        }
-       str = typval_tostring(tv);
+       str = typval_tostring(tv, TRUE);
        clear_tv(tv);
        tv->v_type = VAR_STRING;
        tv->vval.v_string = str;