# HG changeset patch # User Bram Moolenaar # Date 1612095304 -3600 # Node ID d12ef361d9de13883e1fd988b60936fc279a2e2b # Parent 7b30bc27e54bf4a85bf4003762569e790dffcd14 patch 8.2.2435: setline() gives an error for some types Commit: https://github.com/vim/vim/commit/3445320839a38b3b0c253513b125da8298ec27d6 Author: Bram Moolenaar Date: Sun Jan 31 13:08:38 2021 +0100 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. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- 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 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 --- 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 --- 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 --- a/src/proto/typval.pro +++ b/src/proto/typval.pro @@ -21,7 +21,7 @@ char_u *tv_stringify(typval_T *varp, cha 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 --- 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 --- 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 --- 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 --- 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 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -879,7 +879,7 @@ do_2string(typval_T *tv, int is_2string_ return FAIL; } } - str = typval_tostring(tv); + str = typval_tostring(tv, TRUE); clear_tv(tv); tv->v_type = VAR_STRING; tv->vval.v_string = str;