summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-01-31 13:08:38 +0100
committerBram Moolenaar <Bram@vim.org>2021-01-31 13:08:38 +0100
commit3445320839a38b3b0c253513b125da8298ec27d6 (patch)
tree36de5f4e0a019c497710a3cfd6908a5fed0feed4
parentf2b26bcf8f498fed72759af4aa768fb2aab3118c (diff)
patch 8.2.2435: setline() gives an error for some typesv8.2.2435
Problem: setline() gives an error for some types. Solution: Allow any type, convert each item to a string.
-rw-r--r--runtime/doc/eval.txt11
-rw-r--r--src/debugger.c12
-rw-r--r--src/evalbuffer.c9
-rw-r--r--src/proto/typval.pro2
-rw-r--r--src/testdir/test_bufline.vim7
-rw-r--r--src/testdir/test_vim9_builtin.vim48
-rw-r--r--src/typval.c23
-rw-r--r--src/version.c2
-rw-r--r--src/vim9execute.c2
9 files changed, 96 insertions, 20 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index edf5fc8cc3..1c4f46e6bb 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -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.
diff --git a/src/debugger.c b/src/debugger.c
index 4e8a173186..6f52e984d1 100644
--- a/src/debugger.c
+++ b/src/debugger.c
@@ -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;
diff --git a/src/evalbuffer.c b/src/evalbuffer.c
index 3fed3893e9..2ba2f679a5 100644
--- a/src/evalbuffer.c
+++ b/src/evalbuffer.c
@@ -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)
{
diff --git a/src/proto/typval.pro b/src/proto/typval.pro
index 93eb64f4d3..ca4fe96723 100644
--- a/src/proto/typval.pro
+++ b/src/proto/typval.pro
@@ -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);
diff --git a/src/testdir/test_bufline.vim b/src/testdir/test_bufline.vim
index 0f5bac8733..b2de198ef0 100644
--- a/src/testdir/test_bufline.vim
+++ b/src/testdir/test_bufline.vim
@@ -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
diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim
index 2929100162..d9275e617b 100644
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -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
diff --git a/src/typval.c b/src/typval.c
index b3325b663a..65e07b3f79 100644
--- a/src/typval.c
+++ b/src/typval.c
@@ -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;
}
diff --git a/src/version.c b/src/version.c
index 8159289cb2..1347decd54 100644
--- 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 */
/**/
+ 2435,
+/**/
2434,
/**/
2433,
diff --git a/src/vim9execute.c b/src/vim9execute.c
index bcdc5d190a..8a5708cc35 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -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;