Skip to content

Commit 3445320

Browse files
committed
patch 8.2.2435: setline() gives an error for some types
Problem: setline() gives an error for some types. Solution: Allow any type, convert each item to a string.
1 parent f2b26bc commit 3445320

9 files changed

Lines changed: 96 additions & 20 deletions

File tree

runtime/doc/eval.txt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*eval.txt* For Vim version 8.2. Last change: 2021 Jan 22
1+
*eval.txt* For Vim version 8.2. Last change: 2021 Jan 31
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -293,13 +293,13 @@ is not available it returns zero or the default value you specify: >
293293

294294

295295
List concatenation ~
296-
296+
*list-concatenation*
297297
Two lists can be concatenated with the "+" operator: >
298298
:let longlist = mylist + [5, 6]
299299
:let mylist += [7, 8]
300300

301-
To prepend or append an item turn the item into a list by putting [] around
302-
it. To change a list in-place see |list-modification| below.
301+
To prepend or append an item, turn the item into a list by putting [] around
302+
it. To change a list in-place, refer to |list-modification| below.
303303

304304

305305
Sublist ~
@@ -3133,6 +3133,7 @@ append({lnum}, {text}) *append()*
31333133
text line below line {lnum} in the current buffer.
31343134
Otherwise append {text} as one text line below line {lnum} in
31353135
the current buffer.
3136+
Any type of item is accepted and converted to a String.
31363137
{lnum} can be zero to insert a line before the first one.
31373138
Returns 1 for failure ({lnum} out of range or out of memory),
31383139
0 for success. Example: >
@@ -9409,6 +9410,8 @@ setline({lnum}, {text}) *setline()*
94099410
{lnum} is used like with |getline()|.
94109411
When {lnum} is just below the last line the {text} will be
94119412
added below the last line.
9413+
{text} can be any type or a List of any type, each item is
9414+
converted to a String.
94129415

94139416
If this succeeds, FALSE is returned. If this fails (most likely
94149417
because {lnum} is invalid) TRUE is returned.

src/debugger.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -940,9 +940,9 @@ debuggy_find(
940940
{
941941
if (bp->dbg_val == NULL)
942942
{
943-
debug_oldval = typval_tostring(NULL);
943+
debug_oldval = typval_tostring(NULL, TRUE);
944944
bp->dbg_val = tv;
945-
debug_newval = typval_tostring(bp->dbg_val);
945+
debug_newval = typval_tostring(bp->dbg_val, TRUE);
946946
line = TRUE;
947947
}
948948
else
@@ -953,11 +953,11 @@ debuggy_find(
953953
typval_T *v;
954954

955955
line = TRUE;
956-
debug_oldval = typval_tostring(bp->dbg_val);
956+
debug_oldval = typval_tostring(bp->dbg_val, TRUE);
957957
// Need to evaluate again, typval_compare() overwrites
958958
// "tv".
959959
v = eval_expr(bp->dbg_name, NULL);
960-
debug_newval = typval_tostring(v);
960+
debug_newval = typval_tostring(v, TRUE);
961961
free_tv(bp->dbg_val);
962962
bp->dbg_val = v;
963963
}
@@ -966,8 +966,8 @@ debuggy_find(
966966
}
967967
else if (bp->dbg_val != NULL)
968968
{
969-
debug_oldval = typval_tostring(bp->dbg_val);
970-
debug_newval = typval_tostring(NULL);
969+
debug_oldval = typval_tostring(bp->dbg_val, TRUE);
970+
debug_newval = typval_tostring(NULL, TRUE);
971971
free_tv(bp->dbg_val);
972972
bp->dbg_val = NULL;
973973
line = TRUE;

src/evalbuffer.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ find_win_for_curbuf(void)
128128
}
129129

130130
/*
131-
* Set line or list of lines in buffer "buf".
131+
* Set line or list of lines in buffer "buf" to "lines".
132+
* Any type is allowed and converted to a string.
132133
*/
133134
static void
134135
set_buffer_lines(
@@ -187,7 +188,7 @@ set_buffer_lines(
187188
li = l->lv_first;
188189
}
189190
else
190-
line = tv_get_string_chk(lines);
191+
line = typval_tostring(lines, FALSE);
191192

192193
// default result is zero == OK
193194
for (;;)
@@ -197,7 +198,8 @@ set_buffer_lines(
197198
// list argument, get next string
198199
if (li == NULL)
199200
break;
200-
line = tv_get_string_chk(&li->li_tv);
201+
vim_free(line);
202+
line = typval_tostring(&li->li_tv, FALSE);
201203
li = li->li_next;
202204
}
203205

@@ -238,6 +240,7 @@ set_buffer_lines(
238240
break;
239241
++lnum;
240242
}
243+
vim_free(line);
241244

242245
if (added > 0)
243246
{

src/proto/typval.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ char_u *tv_stringify(typval_T *varp, char_u *buf);
2121
int tv_check_lock(typval_T *tv, char_u *name, int use_gettext);
2222
void copy_tv(typval_T *from, typval_T *to);
2323
int typval_compare(typval_T *typ1, typval_T *typ2, exprtype_T type, int ic);
24-
char_u *typval_tostring(typval_T *arg);
24+
char_u *typval_tostring(typval_T *arg, int quotes);
2525
int tv_islocked(typval_T *tv);
2626
int tv_equal(typval_T *tv1, typval_T *tv2, int ic, int recursive);
2727
int eval_option(char_u **arg, typval_T *rettv, int evaluate);

src/testdir/test_bufline.vim

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ source screendump.vim
55
source check.vim
66

77
func Test_setbufline_getbufline()
8+
" similar to Test_set_get_bufline()
89
new
910
let b = bufnr('%')
1011
hide
@@ -38,6 +39,12 @@ func Test_setbufline_getbufline()
3839
call assert_equal(['e'], getbufline(b, 5))
3940
call assert_equal([], getbufline(b, 6))
4041
call assert_equal([], getbufline(b, 2, 1))
42+
43+
call setbufline(b, 2, [function('eval'), #{key: 123}, test_null_job()])
44+
call assert_equal(["function('eval')",
45+
\ "{'key': 123}",
46+
\ "no process"],
47+
\ getbufline(b, 2, 4))
4148
exe "bwipe! " . b
4249
endfunc
4350

src/testdir/test_vim9_builtin.vim

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,54 @@ def Test_searchcount()
767767
bwipe!
768768
enddef
769769

770+
def Test_set_get_bufline()
771+
# similar to Test_setbufline_getbufline()
772+
var lines =<< trim END
773+
new
774+
var b = bufnr('%')
775+
hide
776+
assert_equal(0, setbufline(b, 1, ['foo', 'bar']))
777+
assert_equal(['foo'], getbufline(b, 1))
778+
assert_equal(['bar'], getbufline(b, '$'))
779+
assert_equal(['foo', 'bar'], getbufline(b, 1, 2))
780+
exe "bd!" b
781+
assert_equal([], getbufline(b, 1, 2))
782+
783+
split Xtest
784+
setline(1, ['a', 'b', 'c'])
785+
b = bufnr('%')
786+
wincmd w
787+
788+
assert_equal(1, setbufline(b, 5, 'x'))
789+
assert_equal(1, setbufline(b, 5, ['x']))
790+
assert_equal(1, setbufline(b, 5, []))
791+
assert_equal(1, setbufline(b, 5, test_null_list()))
792+
793+
assert_equal(1, 'x'->setbufline(bufnr('$') + 1, 1))
794+
assert_equal(1, ['x']->setbufline(bufnr('$') + 1, 1))
795+
assert_equal(1, []->setbufline(bufnr('$') + 1, 1))
796+
assert_equal(1, test_null_list()->setbufline(bufnr('$') + 1, 1))
797+
798+
assert_equal(['a', 'b', 'c'], getbufline(b, 1, '$'))
799+
800+
assert_equal(0, setbufline(b, 4, ['d', 'e']))
801+
assert_equal(['c'], b->getbufline(3))
802+
assert_equal(['d'], getbufline(b, 4))
803+
assert_equal(['e'], getbufline(b, 5))
804+
assert_equal([], getbufline(b, 6))
805+
assert_equal([], getbufline(b, 2, 1))
806+
807+
setbufline(b, 2, [function('eval'), {key: 123}, test_null_job()])
808+
assert_equal(["function('eval')",
809+
"{'key': 123}",
810+
"no process"],
811+
getbufline(b, 2, 4))
812+
813+
exe 'bwipe! ' .. b
814+
END
815+
CheckDefAndScriptSuccess(lines)
816+
enddef
817+
770818
def Test_searchdecl()
771819
searchdecl('blah', true, true)->assert_equal(1)
772820
enddef

src/typval.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -927,19 +927,32 @@ typval_compare(
927927
return OK;
928928
}
929929

930+
/*
931+
* Convert any type to a string, never give an error.
932+
* When "quotes" is TRUE add quotes to a string.
933+
* Returns an allocated string.
934+
*/
930935
char_u *
931-
typval_tostring(typval_T *arg)
936+
typval_tostring(typval_T *arg, int quotes)
932937
{
933938
char_u *tofree;
934939
char_u numbuf[NUMBUFLEN];
935940
char_u *ret = NULL;
936941

937942
if (arg == NULL)
938943
return vim_strsave((char_u *)"(does not exist)");
939-
ret = tv2string(arg, &tofree, numbuf, 0);
940-
// Make a copy if we have a value but it's not in allocated memory.
941-
if (ret != NULL && tofree == NULL)
942-
ret = vim_strsave(ret);
944+
if (!quotes && arg->v_type == VAR_STRING)
945+
{
946+
ret = vim_strsave(arg->vval.v_string == NULL ? (char_u *)""
947+
: arg->vval.v_string);
948+
}
949+
else
950+
{
951+
ret = tv2string(arg, &tofree, numbuf, 0);
952+
// Make a copy if we have a value but it's not in allocated memory.
953+
if (ret != NULL && tofree == NULL)
954+
ret = vim_strsave(ret);
955+
}
943956
return ret;
944957
}
945958

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
2435,
753755
/**/
754756
2434,
755757
/**/

src/vim9execute.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,7 @@ do_2string(typval_T *tv, int is_2string_any)
879879
return FAIL;
880880
}
881881
}
882-
str = typval_tostring(tv);
882+
str = typval_tostring(tv, TRUE);
883883
clear_tv(tv);
884884
tv->v_type = VAR_STRING;
885885
tv->vval.v_string = str;

0 commit comments

Comments
 (0)