aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/eval.txt18
-rw-r--r--src/nvim/eval.c35
-rw-r--r--src/nvim/eval.h1
-rw-r--r--src/nvim/eval.lua8
-rw-r--r--src/nvim/option.c1
-rw-r--r--src/nvim/testdir/test_arglist.vim6
-rw-r--r--src/nvim/testdir/test_bufline.vim26
-rw-r--r--src/nvim/testdir/test_messages.vim17
-rw-r--r--src/nvim/window.c3
-rw-r--r--test/functional/api/vim_spec.lua5
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)