diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 82c9a1da67a983..f5cac823150d2f 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -27,6 +27,7 @@ #include "nvim/version.h" #include "nvim/lib/kvec.h" #include "nvim/getchar.h" +#include "nvim/fileio.h" #include "nvim/ui.h" /// Helper structure for vim_to_object @@ -1094,7 +1095,7 @@ static void set_option_value_for(char *key, { win_T *save_curwin = NULL; tabpage_T *save_curtab = NULL; - bufref_T save_curbuf = { NULL, 0, 0 }; + aco_save_T aco; try_start(); switch (opt_type) @@ -1115,9 +1116,9 @@ static void set_option_value_for(char *key, restore_win(save_curwin, save_curtab, true); break; case SREQ_BUF: - switch_buffer(&save_curbuf, (buf_T *)from); + aucmd_prepbuf(&aco, (buf_T *)from); set_option_value_err(key, numval, stringval, opt_flags, err); - restore_buffer(&save_curbuf); + aucmd_restbuf(&aco); break; case SREQ_GLOBAL: set_option_value_err(key, numval, stringval, opt_flags, err); diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 5b59ff39f4e617..86e243c4f0749e 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -955,6 +955,25 @@ void nvim_set_current_win(Window window, Error *err) } } +/// Create new empty buffer +/// +/// @param listed whether the buffer should be listed +/// @param[out] err Error details, if any +/// @return the buffer handle or 0 when error +Buffer nvim_create_buf(Boolean listed, Error *err) + FUNC_API_SINCE(6) +{ + try_start(); + Buffer buffer = buflist_add(NULL, + BLN_NOOPT | BLN_NEW | (listed ? BLN_LISTED : 0)); + if (!try_end(err) && buffer == 0) { + api_set_error(err, + kErrorTypeException, + "Failed to create buffer"); + } + return buffer; +} + /// Gets the current list of tabpage handles. /// /// @return List of tabpage handles diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 802eba06a54a01..7fd43269142643 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1629,7 +1629,7 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags) FileID file_id; bool file_id_valid = (sfname != NULL && os_fileid((char *)sfname, &file_id)); - if (ffname != NULL && !(flags & BLN_DUMMY) + if (ffname != NULL && !(flags & (BLN_DUMMY | BLN_NEW)) && (buf = buflist_findname_file_id(ffname, &file_id, file_id_valid)) != NULL) { xfree(ffname); diff --git a/src/nvim/buffer.h b/src/nvim/buffer.h index e61c312fb1a7a0..79bed049ea8f35 100644 --- a/src/nvim/buffer.h +++ b/src/nvim/buffer.h @@ -31,7 +31,7 @@ enum bln_values { BLN_CURBUF = 1, // May re-use curbuf for new buffer BLN_LISTED = 2, // Put new buffer in buffer list BLN_DUMMY = 4, // Allocating dummy buffer - // TODO(mhinz): merge patch that introduces BLN_NEW + BLN_NEW = 8, // create a new buffer BLN_NOOPT = 16, // Don't copy options to existing buffer }; diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 415eaf3cbc8159..5c0fb8f88d7c41 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1308,4 +1308,41 @@ describe('API', function() eq({["ns-1"]=1, ["ns-2"]=2}, meths.get_namespaces()) end) end) + + describe('nvim_create_buf', function() + it('works', function() + eq({id=2}, meths.create_buf(true)) + eq({id=3}, meths.create_buf(false)) + eq(' 1 %a "[No Name]" line 1\n'.. + ' 2 "[No Name]" line 0', + meths.command_output("ls")) + -- current buffer didn't change + eq({id=1}, meths.get_current_buf()) + + local screen = Screen.new(20, 4) + screen:attach() + meths.buf_set_lines(2, 0, -1, true, {"some text"}) + meths.set_current_buf(2) + screen:expect([[ + ^some text | + {1:~ }| + {1:~ }| + | + ]], { + [1] = {bold = true, foreground = Screen.colors.Blue1}, + }) + end) + + it('can change buftype before visiting', function() + meths.set_option("hidden", false) + eq({id=2}, meths.create_buf(true)) + meths.buf_set_option(2, "buftype", "nofile") + meths.buf_set_lines(2, 0, -1, true, {"test text"}) + command("split | buffer 2") + eq({id=2}, meths.get_current_buf()) + -- if the buf_set_option("buftype") didn't work, this would error out. + command("close") + eq({id=1}, meths.get_current_buf()) + end) + end) end)