# HG changeset patch # User Bram Moolenaar # Date 1561919405 -7200 # Node ID a8fc7d97b54dc1a93bd17082d522e5e759b4b7a8 # Parent 646872542fb30a53800716c57ba8a9e3af2b2e17 patch 8.1.1610: there is no way to add or load a buffer without side effects commit https://github.com/vim/vim/commit/15e248e37f3925d430f96e945d52d3dc423cdc83 Author: Bram Moolenaar Date: Sun Jun 30 20:21:37 2019 +0200 patch 8.1.1610: there is no way to add or load a buffer without side effects Problem: There is no way to add or load a buffer without side effects. Solution: Add the bufadd() and bufload() functions. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2272,8 +2272,10 @@ balloon_split({msg}) List split {msg} a browse({save}, {title}, {initdir}, {default}) String put up a file requester browsedir({title}, {initdir}) String put up a directory requester +bufadd({name}) Number add a buffer to the buffer list bufexists({expr}) Number |TRUE| if buffer {expr} exists buflisted({expr}) Number |TRUE| if buffer {expr} is listed +bufload({expr}) Number load buffer {expr} if not loaded yet bufloaded({expr}) Number |TRUE| if buffer {expr} is loaded bufname({expr}) String Name of the buffer {expr} bufnr({expr} [, {create}]) Number Number of the buffer {expr} @@ -3132,6 +3134,14 @@ browsedir({title}, {initdir}) When the "Cancel" button is hit, something went wrong, or browsing is not possible, an empty string is returned. +bufadd({name}) *bufadd()* + Add a buffer to the buffer list with {name}. + If a buffer for file {name} already exists, return that buffer + number. Otherwise return the buffer number of the newly + created buffer. When {name} is an empty string then a new + buffer is always created. + The buffer will not have' 'buflisted' set. + bufexists({expr}) *bufexists()* The result is a Number, which is |TRUE| if a buffer called {expr} exists. @@ -3161,6 +3171,15 @@ buflisted({expr}) *buflisted()* {expr} exists and is listed (has the 'buflisted' option set). The {expr} argument is used like with |bufexists()|. +bufload({expr}) *bufload()* + Ensure the buffer {expr} is loaded. When the buffer name + refers to an existing file then the file is read. Otherwise + the buffer will be empty. If the buffer was already loaded + then there is no change. + If there is an existing swap file for the file of the buffer, + there will be no dialog, the buffer will be loaded anyway. + The {expr} argument is used like with |bufexists()|. + bufloaded({expr}) *bufloaded()* The result is a Number, which is |TRUE| if a buffer called {expr} exists and is loaded (shown in a window or hidden). diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -71,8 +71,10 @@ static void f_balloon_split(typval_T *ar #endif static void f_browse(typval_T *argvars, typval_T *rettv); static void f_browsedir(typval_T *argvars, typval_T *rettv); +static void f_bufadd(typval_T *argvars, typval_T *rettv); static void f_bufexists(typval_T *argvars, typval_T *rettv); static void f_buflisted(typval_T *argvars, typval_T *rettv); +static void f_bufload(typval_T *argvars, typval_T *rettv); static void f_bufloaded(typval_T *argvars, typval_T *rettv); static void f_bufname(typval_T *argvars, typval_T *rettv); static void f_bufnr(typval_T *argvars, typval_T *rettv); @@ -526,11 +528,13 @@ static struct fst #endif {"browse", 4, 4, f_browse}, {"browsedir", 2, 2, f_browsedir}, + {"bufadd", 1, 1, f_bufadd}, {"bufexists", 1, 1, f_bufexists}, {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */ {"buffer_name", 1, 1, f_bufname}, /* obsolete */ {"buffer_number", 1, 1, f_bufnr}, /* obsolete */ {"buflisted", 1, 1, f_buflisted}, + {"bufload", 1, 1, f_bufload}, {"bufloaded", 1, 1, f_bufloaded}, {"bufname", 1, 1, f_bufname}, {"bufnr", 1, 2, f_bufnr}, @@ -1920,6 +1924,15 @@ find_buffer(typval_T *avar) } /* + * "bufadd(expr)" function + */ + static void +f_bufadd(typval_T *argvars, typval_T *rettv) +{ + rettv->vval.v_number = buflist_add(tv_get_string(&argvars[0]), 0); +} + +/* * "bufexists(expr)" function */ static void @@ -1941,6 +1954,25 @@ f_buflisted(typval_T *argvars, typval_T } /* + * "bufload(expr)" function + */ + static void +f_bufload(typval_T *argvars, typval_T *rettv UNUSED) +{ + buf_T *buf = get_buf_arg(&argvars[0]); + + if (buf != NULL && buf->b_ml.ml_mfp == NULL) + { + aco_save_T aco; + + aucmd_prepbuf(&aco, buf); + swap_exists_action = SEA_NONE; + open_buffer(FALSE, NULL, 0); + aucmd_restbuf(&aco); + } +} + +/* * "bufloaded(expr)" function */ static void diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -1515,3 +1515,31 @@ endfunc func Test_eventhandler() call assert_equal(0, eventhandler()) endfunc + +func Test_bufadd_bufload() + call assert_equal(0, bufexists('someName')) + let buf = bufadd('someName') + call assert_notequal(0, buf) + call assert_equal(1, bufexists('someName')) + call assert_equal(0, getbufvar(buf, '&buflisted')) + call assert_equal(0, bufloaded(buf)) + call bufload(buf) + call assert_equal(1, bufloaded(buf)) + call assert_equal([''], getbufline(buf, 1, '$')) + + let curbuf = bufnr('') + call writefile(['some', 'text'], 'otherName') + let buf = bufadd('otherName') + call assert_notequal(0, buf) + call assert_equal(1, bufexists('otherName')) + call assert_equal(0, getbufvar(buf, '&buflisted')) + call assert_equal(0, bufloaded(buf)) + call bufload(buf) + call assert_equal(1, bufloaded(buf)) + call assert_equal(['some', 'text'], getbufline(buf, 1, '$')) + call assert_equal(curbuf, bufnr('')) + + bwipe someName + bwipe otherName + call assert_equal(0, bufexists('someName')) +endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1610, +/**/ 1609, /**/ 1608,