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 --- src/nvim/api/buffer.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'src/nvim/api') 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| -- 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 +++- 2 files changed, 10 insertions(+), 16 deletions(-) (limited to 'src/nvim/api') 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; -- 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(-) (limited to 'src/nvim/api') 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(-) (limited to 'src/nvim/api') 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 From c146eddc8b768f1cd395ea0ce54c19e64eff0c08 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Tue, 8 Sep 2020 09:47:10 +0200 Subject: api: add API for themes co-author: hlpr98 (dict2hlattrs function) orange is sus?? NOVEMBER DAWN erase the lie that is redraw_later() --- src/nvim/api/buffer.c | 6 +-- src/nvim/api/private/helpers.c | 34 ++++++++++++--- src/nvim/api/vim.c | 95 +++++++++++++++++++++++++++++------------- src/nvim/api/window.c | 4 +- 4 files changed, 100 insertions(+), 39 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index cad4c8314f..4569ebc713 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -974,9 +974,9 @@ 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)) { - force = api_coerce_to_bool(v, "force", false, err); + force = api_object_to_bool(v, "force", false, err); } else if (strequal("unload", k.data)) { - unload = api_coerce_to_bool(v, "unload", false, err); + unload = api_object_to_bool(v, "unload", false, err); } else { api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); return; @@ -1441,7 +1441,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, goto error; } } else if (strequal("ephemeral", k.data)) { - ephemeral = api_coerce_to_bool(*v, "ephemeral", false, err); + ephemeral = api_object_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 981d41ae6e..a9b1676879 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -1625,11 +1625,8 @@ free_exit: /// @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) +bool api_object_to_bool(Object obj, const char *what, + bool nil_value, Error *err) { if (obj.type == kObjectTypeBoolean) { return obj.data.boolean; @@ -1654,3 +1651,30 @@ const char *describe_ns(NS ns_id) }) return "(UNKNOWN PLUGIN)"; } + +DecorationProvider *get_provider(NS ns_id, bool force) +{ + ssize_t i; + for (i = 0; i < (ssize_t)kv_size(decoration_providers); i++) { + DecorationProvider *item = &kv_A(decoration_providers, i); + if (item->ns_id == ns_id) { + return item; + } else if (item->ns_id > ns_id) { + break; + } + } + + if (!force) { + return NULL; + } + + for (ssize_t j = (ssize_t)kv_size(decoration_providers)-1; j >= i; j++) { + // allocates if needed: + (void)kv_a(decoration_providers, (size_t)j+1); + kv_A(decoration_providers, (size_t)j+1) = kv_A(decoration_providers, j); + } + DecorationProvider *item = &kv_a(decoration_providers, (size_t)i); + *item = DECORATION_PROVIDER_INIT(ns_id); + + return item; +} diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 876b052a8e..24d82ccd0f 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -199,6 +199,69 @@ Integer nvim_get_hl_id_by_name(String name) return syn_check_group((const char_u *)name.data, (int)name.size); } +Dictionary nvim__get_hl_defs(Integer ns_id, Error *err) +{ + if (ns_id == 0) { + return get_global_hl_defs(); + } + abort(); +} + +/// Set a highlight group. +/// +/// @param ns_id number of namespace for this highlight +/// @param name highlight group name, like ErrorMsg +/// @param val highlight definiton map, like |nvim_get_hl_by_name|. +/// @param[out] err Error details, if any +/// +/// TODO: ns_id = 0, should modify :highlight namespace +/// TODO val should take update vs reset flag +void nvim_set_hl(Integer ns_id, String name, Dictionary val, Error *err) + FUNC_API_SINCE(7) +{ + int hl_id = syn_check_group( (char_u *)(name.data), (int)name.size); + int link_id = -1; + + HlAttrs attrs = dict2hlattrs(val, true, &link_id, err); + if (!ERROR_SET(err)) { + ns_hl_def((NS)ns_id, hl_id, attrs, link_id); + } +} + +/// Set active namespace for highlights. +/// +/// NB: this function can be called from async contexts, but the +/// semantics are not yet well-defined. To start with +/// |nvim_set_decoration_provider| on_win and on_line callbacks +/// are explicitly allowed to change the namespace during a redraw cycle. +/// +/// @param ns_id the namespace to activate +/// @param[out] err Error details, if any +void nvim_set_hl_ns(Integer ns_id, Error *err) + FUNC_API_SINCE(7) + FUNC_API_FAST +{ + if (ns_id >= 0) { + ns_hl_active = (NS)ns_id; + } + + // TODO(bfredl): this is a little bit hackish. Eventually we want a standard + // event path for redraws caused by "fast" events. This could tie in with + // better throttling of async events causing redraws, such as non-batched + // nvim_buf_set_extmark calls from async contexts. + if (!updating_screen && !ns_hl_changed) { + multiqueue_put(main_loop.events, on_redraw_event, 0); + } + ns_hl_changed = true; +} + +static void on_redraw_event(void **argv) + FUNC_API_NOEXPORT +{ + redraw_all_later(NOT_VALID); +} + + /// Sends input-keys to Nvim, subject to various quirks controlled by `mode` /// flags. This is a blocking call, unlike |nvim_input()|. /// @@ -1477,7 +1540,7 @@ void nvim_unsubscribe(uint64_t channel_id, String event) Integer nvim_get_color_by_name(String name) FUNC_API_SINCE(1) { - return name_to_color((char_u *)name.data); + return name_to_color(name.data); } /// Returns a map of color names and RGB values. @@ -2610,33 +2673,6 @@ void nvim__screenshot(String path) ui_call_screenshot(path); } -static DecorationProvider *get_provider(NS ns_id, bool force) -{ - ssize_t i; - for (i = 0; i < (ssize_t)kv_size(decoration_providers); i++) { - DecorationProvider *item = &kv_A(decoration_providers, i); - if (item->ns_id == ns_id) { - return item; - } else if (item->ns_id > ns_id) { - break; - } - } - - if (!force) { - return NULL; - } - - for (ssize_t j = (ssize_t)kv_size(decoration_providers)-1; j >= i; j++) { - // allocates if needed: - (void)kv_a(decoration_providers, (size_t)j+1); - kv_A(decoration_providers, (size_t)j+1) = kv_A(decoration_providers, j); - } - DecorationProvider *item = &kv_a(decoration_providers, (size_t)i); - *item = DECORATION_PROVIDER_INIT(ns_id); - - return item; -} - static void clear_provider(DecorationProvider *p) { NLUA_CLEAR_REF(p->redraw_start); @@ -2695,7 +2731,7 @@ void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, clear_provider(p); // regardless of what happens, it seems good idea to redraw - redraw_later(NOT_VALID); // TODO(bfredl): too soon? + redraw_all_later(NOT_VALID); // TODO(bfredl): too soon? struct { const char *name; @@ -2706,6 +2742,7 @@ void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, { "on_win", &p->redraw_win }, { "on_line", &p->redraw_line }, { "on_end", &p->redraw_end }, + { "_on_hl_def", &p->hl_def }, { NULL, NULL }, }; diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index ba43bc6cb2..f09a03f592 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -142,7 +142,7 @@ void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err) // make sure cursor is in visible range even if win != curwin update_topline_win(win); - redraw_win_later(win, VALID); + redraw_later(win, VALID); } /// Gets the window height @@ -471,7 +471,7 @@ void nvim_win_set_config(Window window, Dictionary config, Error *err) if (!win_new_float(win, fconfig, err)) { return; } - redraw_later(NOT_VALID); + redraw_later(win, NOT_VALID); } else { win_config_float(win, fconfig); win->w_pos_changed = true; -- cgit From c60c7375f5754eea2a4209cc6441e70b2bb44f14 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Mon, 19 Oct 2020 20:05:54 +0200 Subject: startup: handle autoload and lua packages during startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ¡NO HAY BANDA! --- src/nvim/api/private/helpers.h | 3 ++- src/nvim/api/vim.c | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index df3a263dcf..7c6f07402b 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -52,7 +52,8 @@ .type = kObjectTypeLuaRef, \ .data.luaref = r }) -#define NIL ((Object) {.type = kObjectTypeNil}) +#define NIL ((Object)OBJECT_INIT) +#define NULL_STRING ((String)STRING_INIT) #define PUT(dict, k, v) \ kv_push(dict, ((KeyValuePair) { .key = cstr_to_string(k), .value = v })) diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 24d82ccd0f..725847886a 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -741,7 +741,11 @@ Integer nvim_strwidth(String text, Error *err) ArrayOf(String) nvim_list_runtime_paths(void) FUNC_API_SINCE(1) { + // TODO(bfredl): this should just work: + // return nvim_get_runtime_file(NULL_STRING, true); + Array rv = ARRAY_DICT_INIT; + char_u *rtp = p_rtp; if (*rtp == NUL) { @@ -788,22 +792,29 @@ ArrayOf(String) nvim_list_runtime_paths(void) /// @param name pattern of files to search for /// @param all whether to return all matches or only the first /// @return list of absolute paths to the found files -ArrayOf(String) nvim_get_runtime_file(String name, Boolean all) +ArrayOf(String) nvim_get_runtime_file(String name, Boolean all, Error *err) FUNC_API_SINCE(7) { Array rv = ARRAY_DICT_INIT; - if (!name.data) { + + // TODO(bfredl): + if (name.size == 0) { + api_set_error(err, kErrorTypeValidation, "not yet implemented"); return rv; } + int flags = DIP_START | (all ? DIP_ALL : 0); - do_in_runtimepath((char_u *)name.data, flags, find_runtime_cb, &rv); + do_in_runtimepath(name.size ? (char_u *)name.data : NULL, + flags, find_runtime_cb, &rv); return rv; } static void find_runtime_cb(char_u *fname, void *cookie) { Array *rv = (Array *)cookie; - ADD(*rv, STRING_OBJ(cstr_to_string((char *)fname))); + if (fname != NULL) { + ADD(*rv, STRING_OBJ(cstr_to_string((char *)fname))); + } } String nvim__get_lib_dir(void) -- cgit