# HG changeset patch # User Christian Brabandt # Date 1528389007 -7200 # Node ID cbad3b3f46b2654f5aa325c1c2fa8b11735ce1cc # Parent 3698895e08c6f0fcf2445ed2b446cbd7cd7fd266 patch 8.1.0039: cannot easily delete lines in another buffer commit https://github.com/vim/vim/commit/d79a26219d7161e9211fd144f0e874aa5f6d251e Author: Bram Moolenaar Date: Thu Jun 7 18:17:46 2018 +0200 patch 8.1.0039: cannot easily delete lines in another buffer Problem: Cannot easily delete lines in another buffer. Solution: Add deletebufline(). diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2110,6 +2110,8 @@ cursor({lnum}, {col} [, {off}]) cursor({list}) Number move cursor to position in {list} deepcopy({expr} [, {noref}]) any make a full copy of {expr} delete({fname} [, {flags}]) Number delete the file or directory {fname} +deletebufline({expr}, {first}[, {last}]) + Number delete lines from buffer {expr} did_filetype() Number |TRUE| if FileType autocmd event used diff_filler({lnum}) Number diff filler lines about {lnum} diff_hlID({lnum}, {col}) Number diff highlighting at {lnum}/{col} @@ -3517,8 +3519,19 @@ delete({fname} [, {flags}]) *delete( successful and -1 when the deletion failed or partly failed. Use |remove()| to delete an item from a |List|. - To delete a line from the buffer use |:delete|. Use |:exe| - when the line number is in a variable. + To delete a line from the buffer use |:delete| or + |deletebufline()|. + +deletebufline({expr}, {first}[, {last}]) *deletebufline()* + Delete lines {first} to {last} (inclusive) from buffer {expr}. + If {last} is omitted then delete line {first} only. + On success 0 is returned, on failure 1 is returned. + + For the use of {expr}, see |bufname()| above. + + {first} and {last} are used like with |setline()|. Note that + when using |line()| this refers to the current buffer. Use "$" + to refer to the last line in buffer {expr}. *did_filetype()* did_filetype() Returns |TRUE| when autocommands are being executed and the diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -125,6 +125,7 @@ static void f_cscope_connection(typval_T static void f_cursor(typval_T *argsvars, typval_T *rettv); static void f_deepcopy(typval_T *argvars, typval_T *rettv); static void f_delete(typval_T *argvars, typval_T *rettv); +static void f_deletebufline(typval_T *argvars, typval_T *rettv); static void f_did_filetype(typval_T *argvars, typval_T *rettv); static void f_diff_filler(typval_T *argvars, typval_T *rettv); static void f_diff_hlID(typval_T *argvars, typval_T *rettv); @@ -577,6 +578,7 @@ static struct fst {"cursor", 1, 3, f_cursor}, {"deepcopy", 1, 2, f_deepcopy}, {"delete", 1, 2, f_delete}, + {"deletebufline", 2, 3, f_deletebufline}, {"did_filetype", 0, 0, f_did_filetype}, {"diff_filler", 1, 1, f_diff_filler}, {"diff_hlID", 2, 2, f_diff_hlID}, @@ -1210,6 +1212,24 @@ get_tv_lnum_buf(typval_T *argvars, buf_T } /* + * 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) + { + if (wip->wi_win != NULL) + { + curwin = wip->wi_win; + break; + } + } +} + +/* * Set line or list of lines in buffer "buf". */ static void @@ -1241,19 +1261,10 @@ set_buffer_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(); } if (append) @@ -2808,6 +2819,93 @@ f_delete(typval_T *argvars, typval_T *re } /* + * "deletebufline()" function + */ + static void +f_deletebufline(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + buf_T *buf; + linenr_T first, last; + linenr_T lnum; + long count; + int is_curbuf; + buf_T *curbuf_save = NULL; + win_T *curwin_save = NULL; + tabpage_T *tp; + win_T *wp; + + buf = get_buf_tv(&argvars[0], FALSE); + if (buf == NULL) + { + rettv->vval.v_number = 1; /* FAIL */ + return; + } + is_curbuf = buf == curbuf; + + first = get_tv_lnum_buf(&argvars[1], buf); + if (argvars[2].v_type != VAR_UNKNOWN) + last = get_tv_lnum_buf(&argvars[2], buf); + else + last = first; + + if (buf->b_ml.ml_mfp == NULL || first < 1 + || first > buf->b_ml.ml_line_count || last < first) + { + rettv->vval.v_number = 1; /* FAIL */ + return; + } + + if (!is_curbuf) + { + curbuf_save = curbuf; + curwin_save = curwin; + curbuf = buf; + find_win_for_curbuf(); + } + if (last > curbuf->b_ml.ml_line_count) + last = curbuf->b_ml.ml_line_count; + count = last - first + 1; + + // 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 (u_save(first - 1, last + 1) == FAIL) + { + rettv->vval.v_number = 1; /* FAIL */ + return; + } + + for (lnum = first; lnum <= last; ++lnum) + ml_delete(first, TRUE); + + FOR_ALL_TAB_WINDOWS(tp, wp) + if (wp->w_buffer == buf) + { + if (wp->w_cursor.lnum > last) + wp->w_cursor.lnum -= count; + else if (wp->w_cursor.lnum> first) + wp->w_cursor.lnum = first; + if (wp->w_cursor.lnum > wp->w_buffer->b_ml.ml_line_count) + wp->w_cursor.lnum = wp->w_buffer->b_ml.ml_line_count; + } + check_cursor_col(); + deleted_lines_mark(first, count); + + if (!is_curbuf) + { + curbuf = curbuf_save; + curwin = curwin_save; + } +} + +/* * "did_filetype()" function */ static void diff --git a/src/testdir/test_bufline.vim b/src/testdir/test_bufline.vim --- a/src/testdir/test_bufline.vim +++ b/src/testdir/test_bufline.vim @@ -1,4 +1,4 @@ -" Tests for setbufline(), getbufline(), appendbufline() +" Tests for setbufline(), getbufline(), appendbufline(), deletebufline() source shared.vim @@ -90,3 +90,25 @@ func Test_appendbufline() 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/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -762,6 +762,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 39, +/**/ 38, /**/ 37,