Attached patch implements the delbufline() function. That should address
all the previous complaints. I did intentionally not add a delline()
function, because I thought the gain would be dubious.
Best,
Christian
--
Das beste an der Zukunft ist vielleicht der Umstand, daß immer nur ein
Tag auf einmal kommt.
-- Dean Acheson
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
From 6b67e72b21aeffbac8313a7fd07ca962cab76a2e Mon Sep 17 00:00:00 2001
From: Christian Brabandt <[email protected]>
Date: Fri, 27 Apr 2018 15:01:19 +0200
Subject: [PATCH] delbufline: allow to remove lines in a buffer
delbufline({buf}, {lnum} [, {line}])
delbufline() allows to remove lines {lnum} to {line} in the buffer
{buf}. For the use of {buf} see |bufname()|. If {line} is larger than
{lnum} the start and end lines will silently be swapped. If {line} is
not given, only the single line {lnum} will be deleted.
In addition, add a test, so that the behaviour can be verified.
---
runtime/doc/eval.txt | 13 +++++
runtime/doc/usr_41.txt | 4 +-
src/evalfunc.c | 129 +++++++++++++++++++++++++++++++++++++------
src/testdir/test_bufline.vim | 23 ++++++++
4 files changed, 152 insertions(+), 17 deletions(-)
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 0a22a717c..6e7d34fc6 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2109,6 +2109,9 @@ cursor({lnum}, {col} [, {off}])
Number move cursor to {lnum}, {col}, {off}
cursor({list}) Number move cursor to position in {list}
deepcopy({expr} [, {noref}]) any make a full copy of {expr}
+delbufline({expr}, {lnum} [, {line}])
+ Number delete line {lnum} to {line} in buffer
+ {expr}
delete({fname} [, {flags}]) Number delete the file or directory {fname}
did_filetype() Number |TRUE| if FileType autocmd event used
diff_filler({lnum}) Number diff filler lines about {lnum}
@@ -3481,6 +3484,16 @@ deepcopy({expr} [, {noref}]) *deepcopy()* *E698*
{noref} set to 1 will fail.
Also see |copy()|.
+delbufline({expr}, {lnum} [, {line}]) *delbufline()*
+ Delete line {lnum} to {line} in buffer {expr}.
+
+ For the use of {expr}, see |bufname()| above.
+
+ {lnum} is used like with |setline()|.
+ On success 0 is returned, on failure 1 is returned.
+
+ If {expr} is not a valid buffer an error message is given.
+
delete({fname} [, {flags}]) *delete()*
Without {flags} or with {flags} empty: Deletes the file by the
name {fname}. This also works when {fname} is a symbolic link.
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index bf324e661..7adeff8fb 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -725,7 +725,9 @@ Cursor and mark position: *cursor-functions* *mark-functions*
Working with text in the current buffer: *text-functions*
getline() get a line or list of lines from the buffer
- setline() replace a line in the buffer
+ setline() replace a line in the current buffer
+ setbufline() replace a line in a buffer
+ delbufline() delete a line in a buffer
append() append line or list of lines in the buffer
indent() indent of a specific line
cindent() indent according to C indenting
diff --git a/src/evalfunc.c b/src/evalfunc.c
index ae1425e53..2bab58ba2 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -124,6 +124,7 @@ static void f_cscope_connection(typval_T *argvars, typval_T *rettv);
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_delbufline(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);
@@ -568,6 +569,7 @@ static struct fst
{"cscope_connection",0,3, f_cscope_connection},
{"cursor", 1, 3, f_cursor},
{"deepcopy", 1, 2, f_deepcopy},
+ {"delbufline", 2, 3, f_delbufline},
{"delete", 1, 2, f_delete},
{"did_filetype", 0, 0, f_did_filetype},
{"diff_filler", 1, 1, f_diff_filler},
@@ -1082,6 +1084,22 @@ get_tv_lnum(typval_T *argvars)
return lnum;
}
+/*
+ * 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);
+}
+
#ifdef FEAT_FLOAT
static int get_float_arg(typval_T *argvars, float_T *f);
@@ -2634,6 +2652,100 @@ f_deepcopy(typval_T *argvars, typval_T *rettv)
}
}
+ static void
+delete_buffer_lines(buf_T *buf, linenr_T lnum, linenr_T end, typval_T *rettv)
+{
+ buf_T *curbuf_save = NULL;
+ win_T *curwin_save = NULL;
+ int is_curbuf = buf == curbuf;
+ pos_T curpos = curwin->w_cursor;
+ long lcount;
+ linenr_T max;
+
+ /* When using the current buffer ml_mfp will be set if needed. Useful when
+ * 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;
+ }
+ }
+ }
+
+ max = curbuf->b_ml.ml_line_count;
+
+ if (end > 0 && end < lnum)
+ {
+ /* swap start and end, if end > start */
+ linenr_T t = end;
+ end = lnum;
+ lnum = t;
+ }
+
+ lcount = end ? end - lnum + 1 : 1L;
+ if (lcount > max)
+ lcount = max;
+
+ if (lnum <= max)
+ {
+ curwin->w_cursor.lnum = lnum;
+ del_lines(lcount, TRUE);
+ if (curpos.lnum > curbuf->b_ml.ml_line_count)
+ curpos.lnum = curbuf->b_ml.ml_line_count;
+ curwin->w_cursor = curpos;
+ }
+ else
+ rettv->vval.v_number = 1; /* FAIL */
+
+ if (!is_curbuf)
+ {
+ curbuf = curbuf_save;
+ curwin = curwin_save;
+ }
+}
+
+
+/*
+ * "delbufline()" function
+ */
+ static void
+f_delbufline(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ linenr_T start;
+ linenr_T end = 0;
+ buf_T *buf;
+
+ buf = get_buf_tv(&argvars[0], FALSE);
+
+ if (buf == NULL)
+ rettv->vval.v_number = 1; /* FAIL */
+ else
+ {
+ start = get_tv_lnum_buf(&argvars[1], buf);
+ if (argvars[2].v_type != VAR_UNKNOWN)
+ end = (int)get_tv_number_chk(&argvars[2], NULL);
+
+ delete_buffer_lines(buf, start, end, rettv);
+ }
+}
+
/*
* "delete()" function
*/
@@ -4264,22 +4376,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
*/
@@ -10132,6 +10228,7 @@ f_serverlist(typval_T *argvars UNUSED, typval_T *rettv)
/*
* Set line or list of lines in buffer "buf".
+ * Adds content of *lines to buffer buf at line lnum
*/
static void
set_buffer_lines(buf_T *buf, linenr_T lnum, typval_T *lines, typval_T *rettv)
diff --git a/src/testdir/test_bufline.vim b/src/testdir/test_bufline.vim
index b886e9950..71d2a4d0a 100644
--- a/src/testdir/test_bufline.vim
+++ b/src/testdir/test_bufline.vim
@@ -65,3 +65,26 @@ func Test_setline_startup()
call delete('Xscript')
call delete('Xtest')
endfunc
+
+func Test_delbufline()
+ new
+ let b = bufnr('%')
+ hide
+ call assert_equal(0, setbufline(b, 1, ['foo', 'bar', 'foobar']))
+ call assert_equal(1, delbufline(b, 10))
+ call assert_equal(0, delbufline(b, 1))
+ call assert_equal(['bar', 'foobar'], getbufline(b, 1, 2))
+ call assert_equal(0, delbufline(b, 2, 1))
+ call assert_equal([''], getbufline(b, 1, 2))
+ try
+ " should throw E94
+ call assert_equal(1, delbufline('.', 1))
+ call assert_equal(0, 1)
+ catch /E94/
+ call assert_match(':E94:', v:exception)
+ endtry
+ call assert_equal(0, setbufline(b, 1, ['foo', 'bar', 'foobar']))
+ call assert_equal(0, delbufline(b, 1, 1))
+ call assert_equal(['bar', 'foobar'], getbufline(b, 1, 2))
+ exe "bw!" b
+endfunc
--
2.16.3