diff options
-rw-r--r-- | runtime/doc/eval.txt | 18 | ||||
-rw-r--r-- | src/nvim/eval.c | 35 | ||||
-rw-r--r-- | src/nvim/eval.h | 1 | ||||
-rw-r--r-- | src/nvim/eval.lua | 8 | ||||
-rw-r--r-- | src/nvim/option.c | 1 | ||||
-rw-r--r-- | src/nvim/testdir/test_arglist.vim | 6 | ||||
-rw-r--r-- | src/nvim/testdir/test_bufline.vim | 26 | ||||
-rw-r--r-- | src/nvim/testdir/test_messages.vim | 17 | ||||
-rw-r--r-- | src/nvim/window.c | 3 | ||||
-rw-r--r-- | test/functional/api/vim_spec.lua | 5 |
10 files changed, 98 insertions, 22 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index eac1493a7a..5d30ac15b3 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1529,6 +1529,13 @@ v:dying Normally zero. When a deadly signal is caught it's set to *v:exiting* *exiting-variable* v:exiting Exit code, or |v:null| if not exiting. |VimLeave| + *v:echospace* *echospace-variable* +v:echospace Number of screen cells that can be used for an `:echo` message + in the last screen line before causing the |hit-enter-prompt|. + Depends on 'showcmd', 'ruler' and 'columns'. You need to + check 'cmdheight' for whether there are full-width lines + available above the last line. + *v:errmsg* *errmsg-variable* v:errmsg Last given error message. Modifiable (can be set). @@ -2023,8 +2030,8 @@ bufexists({expr}) Number |TRUE| if buffer {expr} exists buflisted({expr}) Number |TRUE| if buffer {expr} is listed bufload({expr}) Number load buffer {expr} if not loaded yet bufloaded({expr}) Number |TRUE| if buffer {expr} is loaded -bufname({expr}) String Name of the buffer {expr} -bufnr({expr} [, {create}]) Number Number of the buffer {expr} +bufname([{expr}]) String Name of the buffer {expr} +bufnr([{expr} [, {create}]]) Number Number of the buffer {expr} bufwinid({expr}) Number |window-ID| of buffer {expr} bufwinnr({expr}) Number window number of buffer {expr} byte2line({byte}) Number line number at byte count {byte} @@ -2762,9 +2769,10 @@ bufloaded({expr}) *bufloaded()* {expr} exists and is loaded (shown in a window or hidden). The {expr} argument is used like with |bufexists()|. -bufname({expr}) *bufname()* +bufname([{expr}]) *bufname()* The result is the name of a buffer, as it is displayed by the ":ls" command. ++ If {expr} is omitted the current buffer is used. If {expr} is a Number, that buffer number's name is given. Number zero is the alternate buffer for the current window. If {expr} is a String, it is used as a |file-pattern| to match @@ -2791,7 +2799,7 @@ bufname({expr}) *bufname()* bufname("file2") name of buffer where "file2" matches. *bufnr()* -bufnr({expr} [, {create}]) +bufnr([{expr} [, {create}]]) The result is the number of a buffer, as it is displayed by the ":ls" command. For the use of {expr}, see |bufname()| above. @@ -2799,7 +2807,7 @@ bufnr({expr} [, {create}]) {create} argument is present and not zero, a new, unlisted, buffer is created and its number is returned. bufnr("$") is the last buffer: > - :let last_buffer = bufnr("$") + :let last_buffer = bufnr("$") < The result is a Number, which is the highest buffer number of existing buffers. Note that not all buffers with a smaller number necessarily exist, because ":bwipeout" may have removed diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 7b620a03e6..879600b9b1 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -420,6 +420,7 @@ static struct vimvar { VV(VV_TYPE_DICT, "t_dict", VAR_NUMBER, VV_RO), VV(VV_TYPE_FLOAT, "t_float", VAR_NUMBER, VV_RO), VV(VV_TYPE_BOOL, "t_bool", VAR_NUMBER, VV_RO), + VV(VV_ECHOSPACE, "echospace", VAR_NUMBER, VV_RO), VV(VV_EXITING, "exiting", VAR_NUMBER, VV_RO), }; #undef VV @@ -636,6 +637,8 @@ void eval_init(void) set_vim_var_special(VV_NULL, kSpecialVarNull); set_vim_var_special(VV_EXITING, kSpecialVarNull); + set_vim_var_nr(VV_ECHOSPACE, sc_col - 1); + set_reg_var(0); // default for v:register is not 0 but '"' } @@ -7354,14 +7357,19 @@ static buf_T * get_buf_arg(typval_T *arg) */ static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr) { + const buf_T *buf; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - if (!tv_check_str_or_nr(&argvars[0])) { - return; + if (argvars[0].v_type == VAR_UNKNOWN) { + buf = curbuf; + } else { + if (!tv_check_str_or_nr(&argvars[0])) { + return; + } + emsg_off++; + buf = tv_get_buf(&argvars[0], false); + emsg_off--; } - emsg_off++; - const buf_T *const buf = tv_get_buf(&argvars[0], false); - emsg_off--; if (buf != NULL && buf->b_fname != NULL) { rettv->vval.v_string = (char_u *)xstrdup((char *)buf->b_fname); } @@ -7372,15 +7380,21 @@ static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { + const buf_T *buf; bool error = false; rettv->vval.v_number = -1; - if (!tv_check_str_or_nr(&argvars[0])) { - return; + + if (argvars[0].v_type == VAR_UNKNOWN) { + buf = curbuf; + } else { + if (!tv_check_str_or_nr(&argvars[0])) { + return; + } + emsg_off++; + buf = tv_get_buf(&argvars[0], false); + emsg_off--; } - emsg_off++; - const buf_T *buf = tv_get_buf(&argvars[0], false); - emsg_off--; // If the buffer isn't found and the second argument is not zero create a // new buffer. @@ -15209,6 +15223,7 @@ static void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, } } check_cursor_col(); + update_topline(); } if (!is_curbuf) { diff --git a/src/nvim/eval.h b/src/nvim/eval.h index abe032a96e..e099de831a 100644 --- a/src/nvim/eval.h +++ b/src/nvim/eval.h @@ -115,6 +115,7 @@ typedef enum { VV_TYPE_DICT, VV_TYPE_FLOAT, VV_TYPE_BOOL, + VV_ECHOSPACE, VV_EXITING, } VimVarIndex; diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index a21e5a6f5d..ebdf3f5489 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -44,13 +44,13 @@ return { bufadd={args=1}, bufexists={args=1}, buffer_exists={args=1, func='f_bufexists'}, -- obsolete - buffer_name={args=1, func='f_bufname'}, -- obsolete - buffer_number={args=1, func='f_bufnr'}, -- obsolete + buffer_name={args={0, 1}, func='f_bufname'}, -- obsolete + buffer_number={args={0, 1}, func='f_bufnr'}, -- obsolete buflisted={args=1}, bufload={args=1}, bufloaded={args=1}, - bufname={args=1}, - bufnr={args={1, 2}}, + bufname={args={0, 1}}, + bufnr={args={0, 2}}, bufwinid={args=1}, bufwinnr={args=1}, byte2line={args=1}, diff --git a/src/nvim/option.c b/src/nvim/option.c index 699f17acc5..c109e4e521 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -5456,6 +5456,7 @@ void comp_col(void) if (ru_col <= 0) { ru_col = 1; } + set_vim_var_nr(VV_ECHOSPACE, sc_col - 1); } // Unset local option value, similar to ":set opt<". diff --git a/src/nvim/testdir/test_arglist.vim b/src/nvim/testdir/test_arglist.vim index df72ff0a32..6e7583ade3 100644 --- a/src/nvim/testdir/test_arglist.vim +++ b/src/nvim/testdir/test_arglist.vim @@ -379,10 +379,10 @@ func Test_argedit() " make sure to use a new buffer number for x when it is loaded bw! x new - let a = bufnr('') + let a = bufnr() argedit x - call assert_equal(a, bufnr('')) - call assert_equal('x', bufname('')) + call assert_equal(a, bufnr()) + call assert_equal('x', bufname()) %argd bw! x endfunc diff --git a/src/nvim/testdir/test_bufline.vim b/src/nvim/testdir/test_bufline.vim index 1f83e8b776..a924ce0002 100644 --- a/src/nvim/testdir/test_bufline.vim +++ b/src/nvim/testdir/test_bufline.vim @@ -1,6 +1,7 @@ " Tests for setbufline(), getbufline(), appendbufline(), deletebufline() source shared.vim +" source screendump.vim func Test_setbufline_getbufline() new @@ -112,3 +113,28 @@ func Test_deletebufline() call assert_equal(['b', 'c'], getbufline(b, 1, 2)) exe "bwipe! " . b endfunc + +func Test_appendbufline_redraw() + if !CanRunVimInTerminal() + throw 'Skipped: cannot make screendumps' + endif + let lines =<< trim END + new foo + let winnr=bufwinnr('foo') + let buf=bufnr('foo') + wincmd p + call appendbufline(buf, '$', range(1,200)) + exe winnr. 'wincmd w' + norm! G + wincmd p + call deletebufline(buf, 1, '$') + call appendbufline(buf, '$', 'Hello Vim world...') + END + call writefile(lines, 'XscriptMatchCommon') + let buf = RunVimInTerminal('-S XscriptMatchCommon', #{rows: 10}) + call term_wait(buf) + call VerifyScreenDump(buf, 'Test_appendbufline_1', {}) + + call StopVimInTerminal(buf) + call delete('XscriptMatchCommon') +endfunc diff --git a/src/nvim/testdir/test_messages.vim b/src/nvim/testdir/test_messages.vim index 8b71d5f03e..265dee66ce 100644 --- a/src/nvim/testdir/test_messages.vim +++ b/src/nvim/testdir/test_messages.vim @@ -64,3 +64,20 @@ func Test_message_completion() call feedkeys(":message \<C-A>\<C-B>\"\<CR>", 'tx') call assert_equal('"message clear', @:) endfunc + +func Test_echospace() + set noruler noshowcmd laststatus=1 + call assert_equal(&columns - 1, v:echospace) + split + call assert_equal(&columns - 1, v:echospace) + set ruler + call assert_equal(&columns - 1, v:echospace) + close + call assert_equal(&columns - 19, v:echospace) + set showcmd noruler + call assert_equal(&columns - 12, v:echospace) + set showcmd ruler + call assert_equal(&columns - 29, v:echospace) + + set ruler& showcmd& +endfunc diff --git a/src/nvim/window.c b/src/nvim/window.c index 4173245439..b5d34bbbdb 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2698,6 +2698,9 @@ void win_free_all(void) win_T *wp = lastwin; win_remove(lastwin, NULL); (void)win_free_mem(wp, &dummy, NULL); + if (wp == aucmd_win) { + aucmd_win = NULL; + } } if (aucmd_win != NULL) { diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index cd45914552..0cd81619c1 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1510,5 +1510,10 @@ describe('API', function() | ]]) end) + + it('does not cause heap-use-after-free on exit while setting options', function() + command('au OptionSet * q') + command('silent! call nvim_create_buf(0, 1)') + end) end) end) |