aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r--src/nvim/eval.c150
1 files changed, 60 insertions, 90 deletions
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