# HG changeset patch # User Bram Moolenaar # Date 1640691004 -3600 # Node ID b7b82279426f0bee80d138a6e698634556038bfe # Parent ec52a9768f252cbac2cb1102dea950c54bde7742 patch 8.2.3919: Vim9: wrong argument for append() results in two errors Commit: https://github.com/vim/vim/commit/8b6256f6ec075cca40341e61ebc9f538b4902dd1 Author: Bram Moolenaar Date: Tue Dec 28 11:24:49 2021 +0000 patch 8.2.3919: Vim9: wrong argument for append() results in two errors Problem: Vim9: wrong argument for append() results in two errors. Solution: Check did_emsg. Also for setline(). Adjust the help for appendbufline(). diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -806,9 +806,10 @@ appendbufline({buf}, {lnum}, {text}) * For the use of {buf}, see |bufname()|. - {lnum} is used like with |append()|. Note that using |line()| - would use the current buffer, not the one appending to. - Use "$" to append at the end of the buffer. + {lnum} is the line number to append below. Note that using + |line()| would use the current buffer, not the one appending + to. Use "$" to append at the end of the buffer. Other string + values are not supported. On success 0 is returned, on failure 1 is returned. In |Vim9| script an error is given for an invalid {lnum}. diff --git a/src/evalbuffer.c b/src/evalbuffer.c --- a/src/evalbuffer.c +++ b/src/evalbuffer.c @@ -274,12 +274,14 @@ done: f_append(typval_T *argvars, typval_T *rettv) { linenr_T lnum; + int did_emsg_before = did_emsg; if (in_vim9script() && check_for_lnum_arg(argvars, 0) == FAIL) return; lnum = tv_get_lnum(&argvars[0]); - set_buffer_lines(curbuf, lnum, TRUE, &argvars[1], rettv); + if (did_emsg == did_emsg_before) + set_buffer_lines(curbuf, lnum, TRUE, &argvars[1], rettv); } /* @@ -290,6 +292,7 @@ buf_set_append_line(typval_T *argvars, t { linenr_T lnum; buf_T *buf; + int did_emsg_before = did_emsg; if (in_vim9script() && (check_for_buffer_arg(argvars, 0) == FAIL @@ -303,7 +306,8 @@ buf_set_append_line(typval_T *argvars, t else { lnum = tv_get_lnum_buf(&argvars[1], buf); - set_buffer_lines(buf, lnum, append, &argvars[2], rettv); + if (did_emsg == did_emsg_before) + set_buffer_lines(buf, lnum, append, &argvars[2], rettv); } } @@ -502,6 +506,9 @@ f_deletebufline(typval_T *argvars, typva win_T *curwin_save = NULL; tabpage_T *tp; win_T *wp; + int did_emsg_before = did_emsg; + + rettv->vval.v_number = 1; // FAIL by default if (in_vim9script() && (check_for_buffer_arg(argvars, 0) == FAIL @@ -511,13 +518,12 @@ f_deletebufline(typval_T *argvars, typva buf = tv_get_buf(&argvars[0], FALSE); if (buf == NULL) - { - rettv->vval.v_number = 1; // FAIL return; - } is_curbuf = buf == curbuf; first = tv_get_lnum_buf(&argvars[1], buf); + if (did_emsg > did_emsg_before) + return; if (argvars[2].v_type != VAR_UNKNOWN) last = tv_get_lnum_buf(&argvars[2], buf); else @@ -525,10 +531,7 @@ f_deletebufline(typval_T *argvars, typva if (buf->b_ml.ml_mfp == NULL || first < 1 || first > buf->b_ml.ml_line_count || last < first) - { - rettv->vval.v_number = 1; // FAIL return; - } if (!is_curbuf) { @@ -577,6 +580,7 @@ f_deletebufline(typval_T *argvars, typva curbuf = curbuf_save; curwin = curwin_save; } + rettv->vval.v_number = 0; // OK } /* @@ -780,6 +784,7 @@ f_getbufline(typval_T *argvars, typval_T linenr_T lnum = 1; linenr_T end = 1; buf_T *buf; + int did_emsg_before = did_emsg; if (in_vim9script() && (check_for_buffer_arg(argvars, 0) == FAIL @@ -791,6 +796,8 @@ f_getbufline(typval_T *argvars, typval_T if (buf != NULL) { lnum = tv_get_lnum_buf(&argvars[1], buf); + if (did_emsg > did_emsg_before) + return; if (argvars[2].v_type == VAR_UNKNOWN) end = lnum; else @@ -852,12 +859,14 @@ f_setbufline(typval_T *argvars, typval_T f_setline(typval_T *argvars, typval_T *rettv) { linenr_T lnum; + int did_emsg_before = did_emsg; if (in_vim9script() && check_for_lnum_arg(argvars, 0) == FAIL) return; lnum = tv_get_lnum(&argvars[0]); - set_buffer_lines(curbuf, lnum, FALSE, &argvars[1], rettv); + if (did_emsg == did_emsg_before) + set_buffer_lines(curbuf, lnum, FALSE, &argvars[1], rettv); } #endif // FEAT_EVAL 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 @@ -183,7 +183,8 @@ def Test_append() CheckDefAndScriptFailure(['append([1], "x")'], ['E1013: Argument 1: type mismatch, expected string but got list', 'E1220: String or Number required for argument 1']) CheckDefExecAndScriptFailure(['append("", "x")'], 'E1209: Invalid value for a line number') CheckDefExecAndScriptFailure(['append(".a", "x")'], 'E1209: Invalid value for a line number') - CheckDefExecAndScriptFailure(['append("''aa", "x")'], 'E1209: Invalid value for a line number') + # only get one error + assert_fails('append("''aa", "x")', ['E1209: Invalid value for a line number: "''aa"', 'E1209:']) CheckDefExecAndScriptFailure(['append(-1, "x")'], 'E966: Invalid line number: -1') bwipe! enddef @@ -203,6 +204,8 @@ def Test_appendbufline() CheckDefAndScriptFailure(['appendbufline([1], 1, "x")'], ['E1013: Argument 1: type mismatch, expected string but got list', 'E1220: String or Number required for argument 1']) CheckDefAndScriptFailure(['appendbufline(1, [1], "x")'], ['E1013: Argument 2: type mismatch, expected string but got list', 'E1220: String or Number required for argument 2']) CheckDefExecAndScriptFailure(['appendbufline(' .. bnum .. ', -1, "x")'], 'E966: Invalid line number: -1') + CheckDefExecAndScriptFailure(['appendbufline(' .. bnum .. ', "$a", "x")'], 'E1030: Using a String as a Number: "$a"') + assert_fails('appendbufline(' .. bnum .. ', "$a", "x")', ['E1030: Using a String as a Number: "$a"', 'E1030:']) CheckDefAndScriptFailure(['appendbufline(1, 1, {"a": 10})'], ['E1013: Argument 3: type mismatch, expected string but got dict', 'E1224: String, Number or List required for argument 3']) bnum->bufwinid()->win_gotoid() appendbufline('', 0, 'numbers') @@ -768,6 +771,10 @@ def Test_deletebufline() setline(1, ['one', 'two']) deletebufline('', 1) getline(1, '$')->assert_equal(['two']) + + assert_fails('deletebufline("", "$a", "$b")', ['E1030: Using a String as a Number: "$a"', 'E1030: Using a String as a Number: "$a"']) + assert_fails('deletebufline("", "$", "$b")', ['E1030: Using a String as a Number: "$b"', 'E1030: Using a String as a Number: "$b"']) + bwipe! enddef @@ -1459,7 +1466,10 @@ def Test_getbufline() getbufline(-1, '$', '$')->assert_equal([]) getbufline(-1, 1, '$')->assert_equal([]) + assert_fails('getbufline("", "$a", "$b")', ['E1030: Using a String as a Number: "$a"', 'E1030: Using a String as a Number: "$a"']) + assert_fails('getbufline("", "$", "$b")', ['E1030: Using a String as a Number: "$b"', 'E1030: Using a String as a Number: "$b"']) bwipe! + CheckDefAndScriptFailure(['getbufline([], 2)'], ['E1013: Argument 1: type mismatch, expected string but got list', 'E1220: String or Number required for argument 1']) CheckDefAndScriptFailure(['getbufline("a", [])'], ['E1013: Argument 2: type mismatch, expected string but got list', 'E1220: String or Number required for argument 2']) CheckDefAndScriptFailure(['getbufline("a", 2, 0z10)'], ['E1013: Argument 3: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 3']) @@ -3311,6 +3321,7 @@ def Test_setline() CheckDefAndScriptFailure(['setline([1], "x")'], ['E1013: Argument 1: type mismatch, expected string but got list', 'E1220: String or Number required for argument 1']) CheckDefExecAndScriptFailure(['setline("", "x")'], 'E1209: Invalid value for a line number') CheckDefExecAndScriptFailure(['setline(-1, "x")'], 'E966: Invalid line number: -1') + assert_fails('setline(".a", "x")', ['E1209:', 'E1209:']) bw! enddef diff --git a/src/typval.c b/src/typval.c --- a/src/typval.c +++ b/src/typval.c @@ -2249,9 +2249,10 @@ tv_get_lnum(typval_T *argvars) if (lnum <= 0 && argvars[0].v_type != VAR_NUMBER) { int fnum; - pos_T *fp = var2fpos(&argvars[0], TRUE, &fnum, FALSE); + pos_T *fp; // no valid number, try using arg like line() + fp = var2fpos(&argvars[0], TRUE, &fnum, FALSE); if (fp != NULL) lnum = fp->lnum; } @@ -2269,6 +2270,7 @@ tv_get_lnum_buf(typval_T *argvars, buf_T if (argvars[0].v_type == VAR_STRING && argvars[0].vval.v_string != NULL && argvars[0].vval.v_string[0] == '$' + && argvars[0].vval.v_string[1] == NUL && buf != NULL) return buf->b_ml.ml_line_count; return (linenr_T)tv_get_number_chk(&argvars[0], NULL); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3919, +/**/ 3918, /**/ 3917,