From 78556aba7d0934ba92de376c267e3e82f4f77f1d Mon Sep 17 00:00:00 2001 From: TJ DeVries Date: Fri, 9 Oct 2020 15:39:59 -0400 Subject: api: nvim_buf_delete --- runtime/doc/api.txt | 11 ++++++++ src/nvim/api/buffer.c | 55 +++++++++++++++++++++++++++++++++++++ test/functional/api/buffer_spec.lua | 20 ++++++++++++++ 3 files changed, 86 insertions(+) diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 083128ab80..0c726ddd86 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -1783,6 +1783,17 @@ nvim_buf_del_var({buffer}, {name}) *nvim_buf_del_var()* {buffer} Buffer handle, or 0 for current buffer {name} Variable name +nvim_buf_delete({buffer}, {opts}) *nvim_buf_delete()* + Deletes the buffer. See |:bwipeout| + + Parameters: ~ + {buffer} Buffer handle, or 0 for current buffer + {opts} Optional parameters. Keys: + • force: Force deletion and ignore unsaved + changes. + • unload: Unloaded only, do not delete. See + |:bunload| + nvim_buf_detach({buffer}) *nvim_buf_detach()* Deactivates buffer-update events on the channel. diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index c8dd85b39d..ac23c6df92 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -953,6 +953,61 @@ Boolean nvim_buf_is_loaded(Buffer buffer) return buf && buf->b_ml.ml_mfp != NULL; } +#define UNPACK_BOOL_RV(result, v, message, rv) \ + if (v->type == kObjectTypeBoolean) { \ + result = v->data.boolean; \ + } else if (v->type == kObjectTypeInteger) { \ + result = v->data.integer; \ + } else { \ + api_set_error(err, kErrorTypeValidation, message); \ + return rv; \ + } + +#define UNPACK_BOOL(result, v, message) UNPACK_BOOL_RV(result, v, message, ) + +/// Deletes the buffer. See |:bwipeout| +/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param opts Optional parameters. Keys: +/// - force: Force deletion and ignore unsaved changes. +/// - unload: Unloaded only, do not delete. See |:bunload| +void nvim_buf_delete(Buffer buffer, Dictionary opts, Error *err) + FUNC_API_SINCE(7) +{ + buf_T *buf = find_buffer_by_handle(buffer, err); + + if (ERROR_SET(err)) { + return; + } + + bool force = false; + bool unload = false; + for (size_t i = 0; i < opts.size; i++) { + String k = opts.items[i].key; + Object *v = &opts.items[i].value; + if (strequal("force", k.data)) { + UNPACK_BOOL(force, v, "force must be a boolean") + } else if (strequal("unload", k.data)) { + UNPACK_BOOL(unload, v, "unload must be a boolean") + } else { + api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); + return; + } + } + + int result = do_buffer( + unload ? DOBUF_UNLOAD : DOBUF_WIPE, + DOBUF_FIRST, + FORWARD, + buf->handle, + force); + + if (result == FAIL) { + api_set_error(err, kErrorTypeException, "Failed to unload buffer."); + return; + } +} + /// Checks if a buffer is valid. /// /// @note Even if a buffer is valid it may have been unloaded. See |api-buffer| diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua index da7515f012..8ed642b43e 100644 --- a/test/functional/api/buffer_spec.lua +++ b/test/functional/api/buffer_spec.lua @@ -534,6 +534,26 @@ describe('api/buf', function() end) end) + describe('nvim_buf_delete', function() + it('allows for just deleting', function() + nvim('command', 'new') + local b = nvim('get_current_buf') + ok(buffer('is_valid', b)) + nvim('buf_delete', b, {}) + ok(not buffer('is_loaded', b)) + ok(not buffer('is_valid', b)) + end) + + it('allows for just unloading', function() + nvim('command', 'new') + local b = nvim('get_current_buf') + ok(buffer('is_valid', b)) + nvim('buf_delete', b, { unload = true }) + ok(not buffer('is_loaded', b)) + ok(buffer('is_valid', b)) + end) + end) + describe('nvim_buf_get_mark', function() it('works', function() curbuf('set_lines', -1, -1, true, {'a', 'bit of', 'text'}) -- cgit From 1afe6dd2f4578fa7e6758565db36fa36db72b236 Mon Sep 17 00:00:00 2001 From: TJ DeVries Date: Tue, 20 Oct 2020 20:26:53 -0400 Subject: fixup: bfredl comments --- src/nvim/api/buffer.c | 22 +++++++--------------- src/nvim/api/private/helpers.c | 4 +++- src/nvim/screen.c | 2 +- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index ac23c6df92..3c585fd1fd 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -953,18 +953,6 @@ Boolean nvim_buf_is_loaded(Buffer buffer) return buf && buf->b_ml.ml_mfp != NULL; } -#define UNPACK_BOOL_RV(result, v, message, rv) \ - if (v->type == kObjectTypeBoolean) { \ - result = v->data.boolean; \ - } else if (v->type == kObjectTypeInteger) { \ - result = v->data.integer; \ - } else { \ - api_set_error(err, kErrorTypeValidation, message); \ - return rv; \ - } - -#define UNPACK_BOOL(result, v, message) UNPACK_BOOL_RV(result, v, message, ) - /// Deletes the buffer. See |:bwipeout| /// /// @param buffer Buffer handle, or 0 for current buffer @@ -986,15 +974,19 @@ void nvim_buf_delete(Buffer buffer, Dictionary opts, Error *err) String k = opts.items[i].key; Object *v = &opts.items[i].value; if (strequal("force", k.data)) { - UNPACK_BOOL(force, v, "force must be a boolean") + force = api_coerce_to_bool(*v, "force", false, err); } else if (strequal("unload", k.data)) { - UNPACK_BOOL(unload, v, "unload must be a boolean") + unload = api_coerce_to_bool(*v, "unload", false, err); } else { api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); return; } } + if (ERROR_SET(err)) { + return; + } + int result = do_buffer( unload ? DOBUF_UNLOAD : DOBUF_WIPE, DOBUF_FIRST, @@ -1449,7 +1441,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, goto error; } } else if (strequal("ephemeral", k.data)) { - ephemeral = api_is_truthy(*v, "ephemeral", false, err); + ephemeral = api_coerce_to_bool(*v, "ephemeral", false, err); if (ERROR_SET(err)) { goto error; } diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 84517c99fc..dbc4e16d09 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -1619,7 +1619,9 @@ free_exit: return virt_text; } -bool api_is_truthy(Object obj, const char *what, bool nil_truthy, Error *err) +/// Force obj to bool. +/// If it fails, returns false and sets err +bool api_coerce_to_bool(Object obj, const char *what, bool nil_truthy, Error *err) { if (obj.type == kObjectTypeBoolean) { return obj.data.boolean; diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 9f450888a2..df0c5ce791 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -176,7 +176,7 @@ static bool provider_invoke(NS ns_id, const char *name, LuaRef ref, textlock--; if (!ERROR_SET(&err) - && api_is_truthy(ret, "provider %s retval", default_true, &err)) { + && api_coerce_to_bool(ret, "provider %s retval", default_true, &err)) { return true; } -- cgit From 7fca3ddccad2130e75c68e94b5bf4db925b1911b Mon Sep 17 00:00:00 2001 From: TJ DeVries Date: Thu, 22 Oct 2020 14:32:19 -0400 Subject: fixup: some small nit picks --- src/nvim/api/private/helpers.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index dbc4e16d09..41b0f8ae1d 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -1621,14 +1621,18 @@ free_exit: /// Force obj to bool. /// If it fails, returns false and sets err -bool api_coerce_to_bool(Object obj, const char *what, bool nil_truthy, Error *err) +/// @param obj The object to coerce to a boolean +/// @param what The name of the object, used for error message +/// @param if_nil What to return if the type is nil. +/// @param err Set if there was an error in converting to a bool +bool api_coerce_to_bool(Object obj, const char *what, bool if_nil, Error *err) { if (obj.type == kObjectTypeBoolean) { return obj.data.boolean; } else if (obj.type == kObjectTypeInteger) { return obj.data.integer; // C semantics: non-zero int is true } else if (obj.type == kObjectTypeNil) { - return nil_truthy; // caller decides what NIL (missing retval in lua) means + return if_nil; // caller decides what NIL (missing retval in lua) means } else { api_set_error(err, kErrorTypeValidation, "%s is not an boolean", what); return false; -- cgit From a83b76790b82c8f9e74b82c8b0061682b66ddd0d Mon Sep 17 00:00:00 2001 From: TJ DeVries Date: Thu, 22 Oct 2020 16:21:35 -0400 Subject: fixup: fixup: fixup: fixup: --- src/nvim/api/buffer.c | 6 +++--- src/nvim/api/private/helpers.c | 16 ++++++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 3c585fd1fd..cad4c8314f 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -972,11 +972,11 @@ void nvim_buf_delete(Buffer buffer, Dictionary opts, Error *err) bool unload = false; for (size_t i = 0; i < opts.size; i++) { String k = opts.items[i].key; - Object *v = &opts.items[i].value; + Object v = opts.items[i].value; if (strequal("force", k.data)) { - force = api_coerce_to_bool(*v, "force", false, err); + force = api_coerce_to_bool(v, "force", false, err); } else if (strequal("unload", k.data)) { - unload = api_coerce_to_bool(*v, "unload", false, err); + unload = api_coerce_to_bool(v, "unload", false, err); } else { api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); return; diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 41b0f8ae1d..981d41ae6e 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -1621,18 +1621,22 @@ free_exit: /// Force obj to bool. /// If it fails, returns false and sets err -/// @param obj The object to coerce to a boolean -/// @param what The name of the object, used for error message -/// @param if_nil What to return if the type is nil. -/// @param err Set if there was an error in converting to a bool -bool api_coerce_to_bool(Object obj, const char *what, bool if_nil, Error *err) +/// @param obj The object to coerce to a boolean +/// @param what The name of the object, used for error message +/// @param nil_value What to return if the type is nil. +/// @param err Set if there was an error in converting to a bool +bool api_coerce_to_bool( + Object obj, + const char *what, + bool nil_value, + Error *err) { if (obj.type == kObjectTypeBoolean) { return obj.data.boolean; } else if (obj.type == kObjectTypeInteger) { return obj.data.integer; // C semantics: non-zero int is true } else if (obj.type == kObjectTypeNil) { - return if_nil; // caller decides what NIL (missing retval in lua) means + return nil_value; // caller decides what NIL (missing retval in lua) means } else { api_set_error(err, kErrorTypeValidation, "%s is not an boolean", what); return false; -- cgit