diff options
author | Bram Moolenaar <Bram@vim.org> | 2018-06-06 21:04:07 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2018-06-06 21:04:07 +0200 |
commit | ca851593a660f08aba5c134f90c238d4a3e983e6 (patch) | |
tree | 363e4fc7ee646a53d869cb941e09feadc0dd46dc /src/evalfunc.c | |
parent | 891e1fd894720d0b99a9daefa41e8181844f819a (diff) |
patch 8.1.0037: cannot easily append lines to another bufferv8.1.0037
Problem: Cannot easily append lines to another buffer.
Solution: Add appendbufline().
Diffstat (limited to 'src/evalfunc.c')
-rw-r--r-- | src/evalfunc.c | 323 |
1 files changed, 157 insertions, 166 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c index 9441bd89f4..eb379a5cc1 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -40,6 +40,7 @@ static void f_acos(typval_T *argvars, typval_T *rettv); static void f_add(typval_T *argvars, typval_T *rettv); static void f_and(typval_T *argvars, typval_T *rettv); static void f_append(typval_T *argvars, typval_T *rettv); +static void f_appendbufline(typval_T *argvars, typval_T *rettv); static void f_argc(typval_T *argvars, typval_T *rettv); static void f_argidx(typval_T *argvars, typval_T *rettv); static void f_arglistid(typval_T *argvars, typval_T *rettv); @@ -487,6 +488,7 @@ static struct fst {"add", 2, 2, f_add}, {"and", 2, 2, f_and}, {"append", 2, 2, f_append}, + {"appendbufline", 3, 3, f_appendbufline}, {"argc", 0, 0, f_argc}, {"argidx", 0, 0, f_argidx}, {"arglistid", 0, 2, f_arglistid}, @@ -1192,70 +1194,185 @@ f_and(typval_T *argvars, typval_T *rettv) } /* - * "append(lnum, string/list)" function + * Get the lnum from the first argument. + * Also accepts "$", then "buf" is used. + * Returns 0 on error. + */ + static linenr_T +get_tv_lnum_buf(typval_T *argvars, buf_T *buf) +{ + if (argvars[0].v_type == VAR_STRING + && argvars[0].vval.v_string != NULL + && argvars[0].vval.v_string[0] == '$' + && buf != NULL) + return buf->b_ml.ml_line_count; + return (linenr_T)get_tv_number_chk(&argvars[0], NULL); +} + +/* + * Set line or list of lines in buffer "buf". */ static void -f_append(typval_T *argvars, typval_T *rettv) +set_buffer_lines( + buf_T *buf, + linenr_T lnum_arg, + int append, + typval_T *lines, + typval_T *rettv) { - long lnum; - char_u *line; + linenr_T lnum = lnum_arg + (append ? 1 : 0); + char_u *line = NULL; list_T *l = NULL; listitem_T *li = NULL; - typval_T *tv; long added = 0; + linenr_T append_lnum; + buf_T *curbuf_save = NULL; + win_T *curwin_save = NULL; + int is_curbuf = buf == curbuf; - /* 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) + /* 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 + * loaded. */ + if (buf == NULL || (!is_curbuf && buf->b_ml.ml_mfp == NULL) || lnum < 1) { - u_sync_once = 1; /* notify that u_sync() was called */ - u_sync(TRUE); + rettv->vval.v_number = 1; /* FAIL */ + return; } - lnum = get_tv_lnum(argvars); - if (lnum >= 0 - && lnum <= curbuf->b_ml.ml_line_count - && u_save(lnum, lnum + 1) == OK) + if (!is_curbuf) { - if (argvars[1].v_type == VAR_LIST) - { - l = argvars[1].vval.v_list; - if (l == NULL) - return; - li = l->lv_first; - } - for (;;) + wininfo_T *wip; + + curbuf_save = curbuf; + curwin_save = curwin; + curbuf = buf; + for (wip = buf->b_wininfo; wip != NULL; wip = wip->wi_next) { - if (l == NULL) - tv = &argvars[1]; /* append a string */ - else if (li == NULL) - break; /* end of list */ - else - tv = &li->li_tv; /* append item from list */ - line = get_tv_string_chk(tv); - if (line == NULL) /* type error */ + if (wip->wi_win != NULL) { - rettv->vval.v_number = 1; /* Failed */ + curwin = wip->wi_win; break; } - ml_append(lnum + added, line, (colnr_T)0, FALSE); - ++added; - if (l == 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; + li = l->lv_first; + } + else + line = get_tv_string_chk(lines); + + /* default result is zero == OK */ + for (;;) + { + if (l != NULL) + { + /* list argument, get next string */ + if (li == NULL) break; + line = get_tv_string_chk(&li->li_tv); li = li->li_next; } - appended_lines_mark(lnum, added); - if (curwin->w_cursor.lnum > lnum) - curwin->w_cursor.lnum += added; + rettv->vval.v_number = 1; /* FAIL */ + if (line == NULL || lnum > curbuf->b_ml.ml_line_count + 1) + break; + + /* 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); + } + + if (!append && lnum <= curbuf->b_ml.ml_line_count) + { + /* existing line, replace it */ + if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK) + { + changed_bytes(lnum, 0); + if (is_curbuf && lnum == curwin->w_cursor.lnum) + check_cursor_col(); + rettv->vval.v_number = 0; /* OK */ + } + } + else if (added > 0 || u_save(lnum - 1, lnum) == OK) + { + /* append the line */ + ++added; + if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK) + rettv->vval.v_number = 0; /* OK */ + } + + if (l == NULL) /* only one string argument */ + break; + ++lnum; + } + + if (added > 0) + { + win_T *wp; + tabpage_T *tp; + + 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(); + #ifdef FEAT_JOB_CHANNEL if (bt_prompt(curbuf) && (State & INSERT)) // show the line with the prompt update_topline(); #endif } + + if (!is_curbuf) + { + curbuf = curbuf_save; + curwin = curwin_save; + } +} + +/* + * "append(lnum, string/list)" function + */ + static void +f_append(typval_T *argvars, typval_T *rettv) +{ + linenr_T lnum = get_tv_lnum(&argvars[0]); + + set_buffer_lines(curbuf, lnum, TRUE, &argvars[1], rettv); +} + +/* + * "appendbufline(buf, lnum, string/list)" function + */ + static void +f_appendbufline(typval_T *argvars, typval_T *rettv) +{ + linenr_T lnum; + buf_T *buf; + + buf = get_buf_tv(&argvars[0], FALSE); + if (buf == NULL) + rettv->vval.v_number = 1; /* FAIL */ else - rettv->vval.v_number = 1; /* Failed */ + { + lnum = get_tv_lnum_buf(&argvars[1], buf); + set_buffer_lines(buf, lnum, TRUE, &argvars[2], rettv); + } } /* @@ -4276,22 +4393,6 @@ get_buffer_lines( } /* - * Get the lnum from the first argument. - * Also accepts "$", then "buf" is used. - * Returns 0 on error. - */ - static linenr_T -get_tv_lnum_buf(typval_T *argvars, buf_T *buf) -{ - if (argvars[0].v_type == VAR_STRING - && argvars[0].vval.v_string != NULL - && argvars[0].vval.v_string[0] == '$' - && buf != NULL) - return buf->b_ml.ml_line_count; - return (linenr_T)get_tv_number_chk(&argvars[0], NULL); -} - -/* * "getbufline()" function */ static void @@ -10226,115 +10327,6 @@ f_serverlist(typval_T *argvars UNUSED, typval_T *rettv) } /* - * 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) -{ - char_u *line = NULL; - list_T *l = NULL; - listitem_T *li = NULL; - long added = 0; - linenr_T lcount; - buf_T *curbuf_save = NULL; - win_T *curwin_save = NULL; - int 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 - * loaded. */ - if (buf == NULL || (!is_curbuf && buf->b_ml.ml_mfp == NULL) || lnum < 1) - { - rettv->vval.v_number = 1; /* FAIL */ - return; - } - - 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; - } - } - } - - lcount = curbuf->b_ml.ml_line_count; - - if (lines->v_type == VAR_LIST) - { - l = lines->vval.v_list; - li = l->lv_first; - } - else - line = get_tv_string_chk(lines); - - /* default result is zero == OK */ - for (;;) - { - if (l != NULL) - { - /* list argument, get next string */ - if (li == NULL) - break; - line = get_tv_string_chk(&li->li_tv); - li = li->li_next; - } - - rettv->vval.v_number = 1; /* FAIL */ - if (line == NULL || lnum > curbuf->b_ml.ml_line_count + 1) - break; - - /* 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); - } - - if (lnum <= curbuf->b_ml.ml_line_count) - { - /* existing line, replace it */ - if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK) - { - changed_bytes(lnum, 0); - if (is_curbuf && lnum == curwin->w_cursor.lnum) - check_cursor_col(); - 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 */ - ++added; - if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK) - rettv->vval.v_number = 0; /* OK */ - } - - if (l == NULL) /* only one string argument */ - break; - ++lnum; - } - - if (added > 0) - appended_lines_mark(lcount, added); - - if (!is_curbuf) - { - curbuf = curbuf_save; - curwin = curwin_save; - } -} - -/* * "setbufline()" function */ static void @@ -10351,8 +10343,7 @@ f_setbufline(argvars, rettv) else { lnum = get_tv_lnum_buf(&argvars[1], buf); - - set_buffer_lines(buf, lnum, &argvars[2], rettv); + set_buffer_lines(buf, lnum, FALSE, &argvars[2], rettv); } } @@ -10512,7 +10503,7 @@ f_setline(typval_T *argvars, typval_T *rettv) { linenr_T lnum = get_tv_lnum(&argvars[0]); - set_buffer_lines(curbuf, lnum, &argvars[1], rettv); + set_buffer_lines(curbuf, lnum, FALSE, &argvars[1], rettv); } static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *what_arg, typval_T *rettv); |