# HG changeset patch # User Bram Moolenaar # Date 1669060806 -3600 # Node ID 7831da568864beda683a0fdaaec473fdb30a24e6 # Parent 82787a78ff900ff5948b051c03797c44a62a972d patch 9.0.0916: getbufline() is inefficient for getting a single line Commit: https://github.com/vim/vim/commit/ce30ccc06af7f2c03762e5b18dde37b26ea6ec42 Author: Bram Moolenaar Date: Mon Nov 21 19:57:04 2022 +0000 patch 9.0.0916: getbufline() is inefficient for getting a single line Problem: getbufline() is inefficient for getting a single line. Solution: Add getbufoneline(). diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -208,6 +208,7 @@ get({func}, {what}) any get property of getbufinfo([{buf}]) List information about buffers getbufline({buf}, {lnum} [, {end}]) List lines {lnum} to {end} of buffer {buf} +getbufoneline({buf}, {lnum}) String line {lnum} of buffer {buf} getbufvar({buf}, {varname} [, {def}]) any variable {varname} in buffer {buf} getchangelist([{buf}]) List list of change list items @@ -3204,7 +3205,8 @@ getbufinfo([{dict}]) getbufline({buf}, {lnum} [, {end}]) Return a |List| with the lines starting from {lnum} to {end} (inclusive) in the buffer {buf}. If {end} is omitted, a - |List| with only the line {lnum} is returned. + |List| with only the line {lnum} is returned. See + `getbufoneline()` for only getting the line. For the use of {buf}, see |bufname()| above. @@ -3227,6 +3229,11 @@ getbufline({buf}, {lnum} [, {end}]) < Can also be used as a |method|: > GetBufnr()->getbufline(lnum) +< + *getbufoneline()* +getbufoneline({buf}, {lnum}) + Just like `getbufline()` but only get one line and return it + as a string. getbufvar({buf}, {varname} [, {def}]) *getbufvar()* The result is the value of option or local buffer variable @@ -3771,7 +3778,8 @@ getline({lnum} [, {end}]) < Can also be used as a |method|: > ComputeLnum()->getline() -< To get lines from another buffer see |getbufline()| +< To get lines from another buffer see |getbufline()| and + |getbufoneline()| getloclist({nr} [, {what}]) *getloclist()* Returns a |List| with all the entries in the location list for diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -935,6 +935,7 @@ Working with text in the current buffer: Working with text in another buffer: getbufline() get a list of lines from the specified buffer + getbufoneline() get a one line from the specified buffer setbufline() replace a line in the specified buffer appendbufline() append a list of lines in the specified buffer deletebufline() delete lines from a specified buffer diff --git a/src/evalbuffer.c b/src/evalbuffer.c --- a/src/evalbuffer.c +++ b/src/evalbuffer.c @@ -814,10 +814,11 @@ get_buffer_lines( } /* - * "getbufline()" function + * "retlist" TRUE: "getbufline()" function + * "retlist" FALSE: "getbufoneline()" function */ - void -f_getbufline(typval_T *argvars, typval_T *rettv) + static void +getbufline(typval_T *argvars, typval_T *rettv, int retlist) { linenr_T lnum = 1; linenr_T end = 1; @@ -842,7 +843,25 @@ f_getbufline(typval_T *argvars, typval_T end = tv_get_lnum_buf(&argvars[2], buf); } - get_buffer_lines(buf, lnum, end, TRUE, rettv); + get_buffer_lines(buf, lnum, end, retlist, rettv); +} + +/* + * "getbufline()" function + */ + void +f_getbufline(typval_T *argvars, typval_T *rettv) +{ + getbufline(argvars, rettv, TRUE); +} + +/* + * "getbufoneline()" function + */ + void +f_getbufoneline(typval_T *argvars, typval_T *rettv) +{ + getbufline(argvars, rettv, FALSE); } /* diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -1923,6 +1923,8 @@ static funcentry_T global_functions[] = ret_list_dict_any, f_getbufinfo}, {"getbufline", 2, 3, FEARG_1, arg3_buffer_lnum_lnum, ret_list_string, f_getbufline}, + {"getbufoneline", 2, 2, FEARG_1, arg2_buffer_lnum, + ret_string, f_getbufoneline}, {"getbufvar", 2, 3, FEARG_1, arg3_buffer_string_any, ret_any, f_getbufvar}, {"getchangelist", 0, 1, FEARG_1, arg1_buffer, diff --git a/src/proto/evalbuffer.pro b/src/proto/evalbuffer.pro --- a/src/proto/evalbuffer.pro +++ b/src/proto/evalbuffer.pro @@ -16,6 +16,7 @@ void f_bufwinnr(typval_T *argvars, typva void f_deletebufline(typval_T *argvars, typval_T *rettv); void f_getbufinfo(typval_T *argvars, typval_T *rettv); void f_getbufline(typval_T *argvars, typval_T *rettv); +void f_getbufoneline(typval_T *argvars, typval_T *rettv); void f_getline(typval_T *argvars, typval_T *rettv); void f_setbufline(typval_T *argvars, typval_T *rettv); void f_setline(typval_T *argvars, typval_T *rettv); 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 @@ -11,7 +11,9 @@ func Test_setbufline_getbufline() hide call assert_equal(0, setbufline(b, 1, ['foo', 'bar'])) call assert_equal(['foo'], getbufline(b, 1)) + call assert_equal('foo', getbufoneline(b, 1)) call assert_equal(['bar'], getbufline(b, '$')) + call assert_equal('bar', getbufoneline(b, '$')) call assert_equal(['foo', 'bar'], getbufline(b, 1, 2)) exe "bd!" b call assert_equal([], getbufline(b, 1, 2)) @@ -35,8 +37,11 @@ func Test_setbufline_getbufline() call assert_equal(0, setbufline(b, 4, ['d', 'e'])) call assert_equal(['c'], b->getbufline(3)) + call assert_equal('c', b->getbufoneline(3)) call assert_equal(['d'], getbufline(b, 4)) + call assert_equal('d', getbufoneline(b, 4)) call assert_equal(['e'], getbufline(b, 5)) + call assert_equal('e', getbufoneline(b, 5)) call assert_equal([], getbufline(b, 6)) call assert_equal([], getbufline(b, 2, 1)) diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -1724,15 +1724,23 @@ def Test_getbufline() getbufline(-1, '$', '$')->assert_equal([]) getbufline(-1, 1, '$')->assert_equal([]) + getbufoneline('#', 1)->assert_equal(lines[0]) + assert_equal([7, 7, 7], getbufline('#', 1, '$')->map((_, _) => 7)) assert_fails('getbufline("", "$a", "$b")', ['E1030: Using a String as a Number: "$a"', 'E1030: Using a String as a Number: "$a"']) assert_fails('getbufline("", "$", "$b")', ['E1030: Using a String as a Number: "$b"', 'E1030: Using a String as a Number: "$b"']) bwipe! + assert_fails('getbufoneline("", "$a")', ['E1030: Using a String as a Number: "$a"', 'E1030: Using a String as a Number: "$a"']) + bwipe! + v9.CheckDefAndScriptFailure(['getbufline([], 2)'], ['E1013: Argument 1: type mismatch, expected string but got list', 'E1220: String or Number required for argument 1']) v9.CheckDefAndScriptFailure(['getbufline("a", [])'], ['E1013: Argument 2: type mismatch, expected string but got list', 'E1220: String or Number required for argument 2']) v9.CheckDefAndScriptFailure(['getbufline("a", 2, 0z10)'], ['E1013: Argument 3: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 3']) + + v9.CheckDefAndScriptFailure(['getbufoneline([], 2)'], ['E1013: Argument 1: type mismatch, expected string but got list', 'E1220: String or Number required for argument 1']) + v9.CheckDefAndScriptFailure(['getbufoneline("a", [])'], ['E1013: Argument 2: type mismatch, expected string but got list', 'E1220: String or Number required for argument 2']) enddef def Test_getbufvar() diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 916, +/**/ 915, /**/ 914,