aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJan Edmund Lazo <jan.lazo@mail.utoronto.ca>2019-08-22 22:39:28 -0400
committerJan Edmund Lazo <jan.lazo@mail.utoronto.ca>2019-08-23 07:46:51 -0400
commit9358979d096a6bfde371bbca5c77f8d45a4de253 (patch)
tree5572ed3ba56cd16f915ddd4182943b2be3350a98 /src
parentc6eb1f42bec06e92c2c5ee9a523af4e46ac05083 (diff)
downloadrneovim-9358979d096a6bfde371bbca5c77f8d45a4de253.tar.gz
rneovim-9358979d096a6bfde371bbca5c77f8d45a4de253.tar.bz2
rneovim-9358979d096a6bfde371bbca5c77f8d45a4de253.zip
vim-patch:8.1.0037: cannot easily append lines to another buffer
Problem: Cannot easily append lines to another buffer. Solution: Add appendbufline(). https://github.com/vim/vim/commit/ca851593a660f08aba5c134f90c238d4a3e983e6
Diffstat (limited to 'src')
-rw-r--r--src/nvim/eval.c109
-rw-r--r--src/nvim/eval.lua1
-rw-r--r--src/nvim/testdir/test_bufline.vim27
-rw-r--r--src/nvim/testdir/test_edit.vim2
4 files changed, 71 insertions, 68 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 8f6d6cd55e..df8a23f9a5 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -6741,61 +6741,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)
@@ -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
@@ -15163,9 +15129,14 @@ static void set_buffer_lines(buf_T *buf, linenr_T lnum, typval_T *lines,
}
}
- 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 +15168,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 +15179,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 +15219,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 +15370,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..b110c44eb1 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()
source shared.vim
@@ -65,3 +65,28 @@ 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
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