aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2019-08-23 19:39:04 +0200
committerGitHub <noreply@github.com>2019-08-23 19:39:04 +0200
commit82aaac5baafb4101022604c5e720e37987279184 (patch)
treea755fb4e7644d7c85604e9e1f7c8e22be0d68b24
parent79ea7709b7cab13b89d98088f4733a354a7f2a54 (diff)
parent2a1887c2df27c5f91f0f2f6ad6c70da60239cfce (diff)
downloadrneovim-82aaac5baafb4101022604c5e720e37987279184.tar.gz
rneovim-82aaac5baafb4101022604c5e720e37987279184.tar.bz2
rneovim-82aaac5baafb4101022604c5e720e37987279184.zip
Merge #10833 from janlazo/vim-8.1.0037
vim-patch:8.0.1386,8.1.{37,39,187}
-rw-r--r--runtime/doc/eval.txt56
-rw-r--r--src/nvim/eval.c150
-rw-r--r--src/nvim/eval.lua1
-rw-r--r--src/nvim/testdir/test_bufline.vim49
-rw-r--r--src/nvim/testdir/test_bufwintabinfo.vim26
-rw-r--r--src/nvim/testdir/test_edit.vim2
6 files changed, 163 insertions, 121 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 5e8c5151f2..de2650baa4 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2495,6 +2495,21 @@ append({lnum}, {text}) *append()*
0 for success. Example: >
:let failed = append(line('$'), "# THE END")
:let failed = append(0, ["Chapter 1", "the beginning"])
+
+appendbufline({expr}, {lnum}, {text}) *appendbufline()*
+ Like |append()| but append the text in buffer {expr}.
+
+ For the use of {expr}, 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.
+
+ On success 0 is returned, on failure 1 is returned.
+
+ If {expr} is not a valid buffer or {lnum} is not valid, an
+ error message is given. Example: >
+ :let failed = appendbufline(13, 0, "# THE START")
<
*argc()*
argc([{winid}])
@@ -4026,6 +4041,7 @@ getbufinfo([{dict}])
be specified in {dict}:
buflisted include only listed buffers.
bufloaded include only loaded buffers.
+ bufmodified include only modified buffers.
Otherwise, {expr} specifies a particular buffer to return
information for. For the use of {expr}, see |bufname()|
@@ -4725,25 +4741,6 @@ gettagstack([{nr}]) *gettagstack()*
See |tagstack| for more information about the tag stack.
-getwinpos([{timeout}]) *getwinpos()*
- The result is a list with two numbers, the result of
- getwinposx() and getwinposy() combined:
- [x-pos, y-pos]
- {timeout} can be used to specify how long to wait in msec for
- a response from the terminal. When omitted 100 msec is used.
-
- *getwinposx()*
-getwinposx() The result is a Number, which is the X coordinate in pixels of
- the left hand side of the GUI Vim window. The result will be
- -1 if the information is not available.
- The value can be used with `:winpos`.
-
- *getwinposy()*
-getwinposy() The result is a Number, which is the Y coordinate in pixels of
- the top of the GUI Vim window. The result will be -1 if the
- information is not available.
- The value can be used with `:winpos`.
-
getwininfo([{winid}]) *getwininfo()*
Returns information about windows as a List with Dictionaries.
@@ -4773,6 +4770,25 @@ getwininfo([{winid}]) *getwininfo()*
winnr window number
winrow topmost screen column of the window
+getwinpos([{timeout}]) *getwinpos()*
+ The result is a list with two numbers, the result of
+ getwinposx() and getwinposy() combined:
+ [x-pos, y-pos]
+ {timeout} can be used to specify how long to wait in msec for
+ a response from the terminal. When omitted 100 msec is used.
+
+ *getwinposx()*
+getwinposx() The result is a Number, which is the X coordinate in pixels of
+ the left hand side of the GUI Vim window. The result will be
+ -1 if the information is not available.
+ The value can be used with `:winpos`.
+
+ *getwinposy()*
+getwinposy() The result is a Number, which is the Y coordinate in pixels of
+ the top of the GUI Vim window. The result will be -1 if the
+ information is not available.
+ The value can be used with `:winpos`.
+
getwinvar({winnr}, {varname} [, {def}]) *getwinvar()*
Like |gettabwinvar()| for the current tabpage.
Examples: >
@@ -8872,7 +8888,7 @@ win_id2win({expr}) *win_id2win()*
win_screenpos({nr}) *win_screenpos()*
Return the screen position of window {nr} as a list with two
numbers: [row, col]. The first window always has position
- [1, 1].
+ [1, 1], unless there is a tabline, then it is [2, 1].
{nr} can be the window number or the |window-ID|.
Return [0, 0] if the window cannot be found in the current
tabpage.
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 8f6d6cd55e..3d56522f79 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -1224,9 +1224,7 @@ static void restore_vimvar(int idx, typval_T *save_tv)
/// If there is a window for "curbuf", make it the current window.
static void find_win_for_curbuf(void)
{
- wininfo_T *wip;
-
- for (wip = curbuf->b_wininfo; wip != NULL; wip = wip->wi_next) {
+ for (wininfo_T *wip = curbuf->b_wininfo; wip != NULL; wip = wip->wi_next) {
if (wip->wi_win != NULL) {
curwin = wip->wi_win;
break;
@@ -6741,61 +6739,24 @@ static void f_api_info(typval_T *argvars, typval_T *rettv, FunPtr fptr)
api_free_dictionary(metadata);
}
-/*
- * "append(lnum, string/list)" function
- */
+// "append(lnum, string/list)" function
static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- long lnum;
- list_T *l = NULL;
- listitem_T *li = NULL;
- typval_T *tv;
- long added = 0;
+ const linenr_T lnum = tv_get_lnum(&argvars[0]);
- /* When coming here from Insert mode, sync undo, so that this can be
- * undone separately from what was previously inserted. */
- if (u_sync_once == 2) {
- u_sync_once = 1; /* notify that u_sync() was called */
- u_sync(TRUE);
- }
-
- lnum = tv_get_lnum(argvars);
- if (lnum >= 0
- && lnum <= curbuf->b_ml.ml_line_count
- && u_save(lnum, lnum + 1) == OK) {
- if (argvars[1].v_type == VAR_LIST) {
- l = argvars[1].vval.v_list;
- if (l == NULL) {
- return;
- }
- li = tv_list_first(l);
- }
- for (;; ) {
- if (l == NULL) {
- tv = &argvars[1]; // Append a string.
- } else if (li == NULL) {
- break; // End of list.
- } else {
- tv = TV_LIST_ITEM_TV(li); // Append item from list.
- }
- const char *const line = tv_get_string_chk(tv);
- if (line == NULL) { // Type error.
- rettv->vval.v_number = 1; // Failed.
- break;
- }
- ml_append(lnum + added, (char_u *)line, (colnr_T)0, false);
- added++;
- if (l == NULL) {
- break;
- }
- li = TV_LIST_ITEM_NEXT(l, li);
- }
+ set_buffer_lines(curbuf, lnum, true, &argvars[1], rettv);
+}
- appended_lines_mark(lnum, added);
- if (curwin->w_cursor.lnum > lnum)
- curwin->w_cursor.lnum += added;
- } else
- rettv->vval.v_number = 1; /* Failed */
+// "appendbufline(buf, lnum, string/list)" function
+static void f_appendbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ buf_T *const buf = tv_get_buf(&argvars[0], false);
+ if (buf == NULL) {
+ rettv->vval.v_number = 1; // FAIL
+ } else {
+ const linenr_T lnum = tv_get_lnum_buf(&argvars[1], buf);
+ set_buffer_lines(buf, lnum, true, &argvars[2], rettv);
+ }
}
static void f_argc(typval_T *argvars, typval_T *rettv, FunPtr fptr)
@@ -8297,22 +8258,18 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// "deletebufline()" function
static void f_deletebufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- buf_T *buf;
- linenr_T first, last;
- linenr_T lnum;
- long count;
- int is_curbuf;
+ linenr_T last;
buf_T *curbuf_save = NULL;
win_T *curwin_save = NULL;
- buf = tv_get_buf(&argvars[0], false);
+ buf_T *const buf = tv_get_buf(&argvars[0], false);
if (buf == NULL) {
rettv->vval.v_number = 1; // FAIL
return;
}
- is_curbuf = buf == curbuf;
+ const bool is_curbuf = buf == curbuf;
- first = tv_get_lnum_buf(&argvars[1], buf);
+ const linenr_T first = tv_get_lnum_buf(&argvars[1], buf);
if (argvars[2].v_type != VAR_UNKNOWN) {
last = tv_get_lnum_buf(&argvars[2], buf);
} else {
@@ -8334,7 +8291,7 @@ static void f_deletebufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (last > curbuf->b_ml.ml_line_count) {
last = curbuf->b_ml.ml_line_count;
}
- count = last - first + 1;
+ const long count = last - first + 1;
// When coming here from Insert mode, sync undo, so that this can be
// undone separately from what was previously inserted.
@@ -8348,7 +8305,7 @@ static void f_deletebufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
- for (lnum = first; lnum <= last; lnum++) {
+ for (linenr_T lnum = first; lnum <= last; lnum++) {
ml_delete(first, true);
}
@@ -9735,6 +9692,7 @@ static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
bool filtered = false;
bool sel_buflisted = false;
bool sel_bufloaded = false;
+ bool sel_bufmodified = false;
tv_list_alloc_ret(rettv, kListLenMayKnow);
@@ -9756,6 +9714,10 @@ static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (di != NULL && tv_get_number(&di->di_tv)) {
sel_bufloaded = true;
}
+ di = tv_dict_find(sel_d, S_LEN("bufmodified"));
+ if (di != NULL && tv_get_number(&di->di_tv)) {
+ sel_bufmodified = true;
+ }
}
} else if (argvars[0].v_type != VAR_UNKNOWN) {
// Information about one buffer. Argument specifies the buffer
@@ -9775,7 +9737,8 @@ static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
continue;
}
if (filtered && ((sel_bufloaded && buf->b_ml.ml_mfp == NULL)
- || (sel_buflisted && !buf->b_p_bl))) {
+ || (sel_buflisted && !buf->b_p_bl)
+ || (sel_bufmodified && !buf->b_changed))) {
continue;
}
@@ -10876,12 +10839,12 @@ static dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr)
tv_dict_add_nr(dict, S_LEN("winnr"), winnr);
tv_dict_add_nr(dict, S_LEN("winid"), wp->handle);
tv_dict_add_nr(dict, S_LEN("height"), wp->w_height);
- tv_dict_add_nr(dict, S_LEN("winrow"), wp->w_winrow);
+ tv_dict_add_nr(dict, S_LEN("winrow"), wp->w_winrow + 1);
tv_dict_add_nr(dict, S_LEN("topline"), wp->w_topline);
tv_dict_add_nr(dict, S_LEN("botline"), wp->w_botline - 1);
tv_dict_add_nr(dict, S_LEN("width"), wp->w_width);
tv_dict_add_nr(dict, S_LEN("bufnr"), wp->w_buffer->b_fnum);
- tv_dict_add_nr(dict, S_LEN("wincol"), wp->w_wincol);
+ tv_dict_add_nr(dict, S_LEN("wincol"), wp->w_wincol + 1);
tv_dict_add_nr(dict, S_LEN("terminal"), bt_terminal(wp->w_buffer));
tv_dict_add_nr(dict, S_LEN("quickfix"), bt_quickfix(wp->w_buffer));
@@ -15130,16 +15093,19 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// Set line or list of lines in buffer "buf".
-static void set_buffer_lines(buf_T *buf, linenr_T lnum, typval_T *lines,
- typval_T *rettv)
+static void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append,
+ const typval_T *lines, typval_T *rettv)
+ FUNC_ATTR_NONNULL_ARG(4, 5)
{
+ linenr_T lnum = lnum_arg + (append ? 1 : 0);
+ const char *line = NULL;
list_T *l = NULL;
listitem_T *li = NULL;
long added = 0;
- linenr_T lcount;
+ linenr_T append_lnum;
buf_T *curbuf_save = NULL;
win_T *curwin_save = NULL;
- int is_curbuf = buf == curbuf;
+ const bool is_curbuf = buf == curbuf;
// When using the current buffer ml_mfp will be set if needed. Useful when
// setline() is used on startup. For other buffers the buffer must be
@@ -15150,22 +15116,20 @@ static void set_buffer_lines(buf_T *buf, linenr_T lnum, typval_T *lines,
}
if (!is_curbuf) {
- wininfo_T *wip;
-
curbuf_save = curbuf;
curwin_save = curwin;
curbuf = buf;
- for (wip = buf->b_wininfo; wip != NULL; wip = wip->wi_next) {
- if (wip->wi_win != NULL) {
- curwin = wip->wi_win;
- break;
- }
- }
+ find_win_for_curbuf();
}
- lcount = curbuf->b_ml.ml_line_count;
-
- const char *line = NULL;
+ if (append) {
+ // appendbufline() uses the line number below which we insert
+ append_lnum = lnum - 1;
+ } else {
+ // setbufline() uses the line number above which we insert, we only
+ // append if it's below the last line
+ append_lnum = curbuf->b_ml.ml_line_count;
+ }
if (lines->v_type == VAR_LIST) {
l = lines->vval.v_list;
@@ -15197,7 +15161,7 @@ static void set_buffer_lines(buf_T *buf, linenr_T lnum, typval_T *lines,
u_sync(true);
}
- if (lnum <= curbuf->b_ml.ml_line_count) {
+ if (!append && lnum <= curbuf->b_ml.ml_line_count) {
// Existing line, replace it.
if (u_savesub(lnum) == OK
&& ml_replace(lnum, (char_u *)line, true) == OK) {
@@ -15208,20 +15172,27 @@ static void set_buffer_lines(buf_T *buf, linenr_T lnum, typval_T *lines,
rettv->vval.v_number = 0; // OK
}
} else if (added > 0 || u_save(lnum - 1, lnum) == OK) {
- // lnum is one past the last line, append the line.
+ // append the line.
added++;
if (ml_append(lnum - 1, (char_u *)line, 0, false) == OK) {
rettv->vval.v_number = 0; // OK
}
}
- if (l == NULL) /* only one string argument */
+ if (l == NULL) { // only one string argument
break;
- ++lnum;
+ }
+ lnum++;
}
if (added > 0) {
- appended_lines_mark(lcount, added);
+ appended_lines_mark(append_lnum, added);
+ FOR_ALL_TAB_WINDOWS(tp, wp) {
+ if (wp->w_buffer == buf && wp->w_cursor.lnum > append_lnum) {
+ wp->w_cursor.lnum += added;
+ }
+ }
+ check_cursor_col();
}
if (!is_curbuf) {
@@ -15241,8 +15212,7 @@ static void f_setbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = 1; // FAIL
} else {
lnum = tv_get_lnum_buf(&argvars[1], buf);
-
- set_buffer_lines(buf, lnum, &argvars[2], rettv);
+ set_buffer_lines(buf, lnum, false, &argvars[2], rettv);
}
}
@@ -15393,7 +15363,7 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum = tv_get_lnum(&argvars[0]);
- set_buffer_lines(curbuf, lnum, &argvars[1], rettv);
+ set_buffer_lines(curbuf, lnum, false, &argvars[1], rettv);
}
/// Create quickfix/location list from VimL values
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index db45409e77..6b63003e69 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -20,6 +20,7 @@ return {
['and']={args=2},
api_info={},
append={args=2},
+ appendbufline={args=3},
argc={args={0, 1}},
argidx={},
arglistid={args={0, 2}},
diff --git a/src/nvim/testdir/test_bufline.vim b/src/nvim/testdir/test_bufline.vim
index b886e99506..1f83e8b776 100644
--- a/src/nvim/testdir/test_bufline.vim
+++ b/src/nvim/testdir/test_bufline.vim
@@ -1,4 +1,4 @@
-" Tests for setbufline() and getbufline()
+" Tests for setbufline(), getbufline(), appendbufline(), deletebufline()
source shared.vim
@@ -65,3 +65,50 @@ func Test_setline_startup()
call delete('Xscript')
call delete('Xtest')
endfunc
+
+func Test_appendbufline()
+ new
+ let b = bufnr('%')
+ hide
+ call assert_equal(0, appendbufline(b, 0, ['foo', 'bar']))
+ call assert_equal(['foo'], getbufline(b, 1))
+ call assert_equal(['bar'], getbufline(b, 2))
+ call assert_equal(['foo', 'bar'], getbufline(b, 1, 2))
+ exe "bd!" b
+ call assert_equal([], getbufline(b, 1, 2))
+
+ split Xtest
+ call setline(1, ['a', 'b', 'c'])
+ let b = bufnr('%')
+ wincmd w
+ call assert_equal(1, appendbufline(b, 4, ['x']))
+ call assert_equal(1, appendbufline(1234, 1, ['x']))
+ call assert_equal(0, appendbufline(b, 3, ['d', 'e']))
+ call assert_equal(['c'], getbufline(b, 3))
+ call assert_equal(['d'], getbufline(b, 4))
+ call assert_equal(['e'], getbufline(b, 5))
+ call assert_equal([], getbufline(b, 6))
+ exe "bwipe! " . b
+endfunc
+
+func Test_deletebufline()
+ new
+ let b = bufnr('%')
+ call setline(1, ['aaa', 'bbb', 'ccc'])
+ hide
+ call assert_equal(0, deletebufline(b, 2))
+ call assert_equal(['aaa', 'ccc'], getbufline(b, 1, 2))
+ call assert_equal(0, deletebufline(b, 2, 8))
+ call assert_equal(['aaa'], getbufline(b, 1, 2))
+ exe "bd!" b
+ call assert_equal(1, deletebufline(b, 1))
+
+ split Xtest
+ call setline(1, ['a', 'b', 'c'])
+ let b = bufnr('%')
+ wincmd w
+ call assert_equal(1, deletebufline(b, 4))
+ call assert_equal(0, deletebufline(b, 1))
+ call assert_equal(['b', 'c'], getbufline(b, 1, 2))
+ exe "bwipe! " . b
+endfunc
diff --git a/src/nvim/testdir/test_bufwintabinfo.vim b/src/nvim/testdir/test_bufwintabinfo.vim
index a6b4524cc0..0e8c7d1dc1 100644
--- a/src/nvim/testdir/test_bufwintabinfo.vim
+++ b/src/nvim/testdir/test_bufwintabinfo.vim
@@ -20,6 +20,13 @@ function Test_getbufwintabinfo()
call assert_equal('vim', l[0].variables.editor)
call assert_notequal(-1, index(l[0].windows, bufwinid('%')))
+ " Test for getbufinfo() with 'bufmodified'
+ call assert_equal(0, len(getbufinfo({'bufmodified' : 1})))
+ call setbufline('Xtestfile1', 1, ["Line1"])
+ let l = getbufinfo({'bufmodified' : 1})
+ call assert_equal(1, len(l))
+ call assert_equal(bufnr('Xtestfile1'), l[0].bufnr)
+
if has('signs')
call append(0, ['Linux', 'Windows', 'Mac'])
sign define Mark text=>> texthl=Search
@@ -45,21 +52,22 @@ function Test_getbufwintabinfo()
let winlist = getwininfo()
call assert_equal(5, len(winlist))
call assert_equal(winwidth(1), winlist[0].width)
- call assert_equal(0, winlist[0].wincol)
- let tablineheight = winlist[0].winrow == 1 ? 1 : 0
- call assert_equal(tablineheight, winlist[0].winrow) " tabline adds one
+ call assert_equal(1, winlist[0].wincol)
+ " tabline adds one row in terminal, not in GUI
+ let tablineheight = winlist[0].winrow == 2 ? 1 : 0
+ call assert_equal(tablineheight + 1, winlist[0].winrow)
call assert_equal(winbufnr(2), winlist[1].bufnr)
call assert_equal(winheight(2), winlist[1].height)
- call assert_equal(0, winlist[1].wincol)
- call assert_equal(tablineheight + winheight(1) + 1, winlist[1].winrow)
+ call assert_equal(1, winlist[1].wincol)
+ call assert_equal(tablineheight + winheight(1) + 2, winlist[1].winrow)
call assert_equal(1, winlist[2].winnr)
- call assert_equal(tablineheight, winlist[2].winrow)
- call assert_equal(0, winlist[2].wincol)
+ call assert_equal(tablineheight + 1, winlist[2].winrow)
+ call assert_equal(1, winlist[2].wincol)
- call assert_equal(winlist[2].width + 1, winlist[3].wincol)
- call assert_equal(0, winlist[4].wincol)
+ call assert_equal(winlist[2].width + 2, winlist[3].wincol)
+ call assert_equal(1, winlist[4].wincol)
call assert_equal(1, winlist[0].tabnr)
call assert_equal(1, winlist[1].tabnr)
diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim
index 827c54e704..1010ae4e09 100644
--- a/src/nvim/testdir/test_edit.vim
+++ b/src/nvim/testdir/test_edit.vim
@@ -537,7 +537,7 @@ func! Test_edit_CTRL_I()
" Tab in completion mode
let path=expand("%:p:h")
new
- call setline(1, [path."/", ''])
+ call setline(1, [path. "/", ''])
call feedkeys("Arunt\<c-x>\<c-f>\<tab>\<cr>\<esc>", 'tnix')
call assert_match('runtest\.vim', getline(1))
%d