From 7ab152aaa58f493e54d03a15960b8a288196e588 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 1 Jul 2017 15:34:25 +0300 Subject: ex_getln: Save and restore try state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: when processing cycle such as :for pat in [' \ze*', ' \zs*'] : try : let l = matchlist('x x', pat) : $put ='E888 NOT detected for ' . pat : catch : $put ='E888 detected for ' . pat : endtry :endfor `:let l = …` throwing an error causes this error to be caught after color_cmdline attempts to get callback for highlighting next line (the one with `$put = 'E888 NOT…`). Saving/restoring state prevents this from happening. --- src/nvim/api/private/helpers.c | 46 ++++++++++++++++++++++++++++++++++++++++++ src/nvim/api/private/helpers.h | 12 +++++++++++ 2 files changed, 58 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index d401ae52a0..883a5a2fd1 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -37,6 +37,52 @@ typedef struct { # include "api/private/ui_events_metadata.generated.h" #endif +/// Start block that may cause VimL exceptions while evaluating another code +/// +/// Used when caller is supposed to be operating when other VimL code is being +/// processed and that “other VimL code” must not be affected. +/// +/// @param[out] tstate Location where try state should be saved. +void try_enter(TryState *const tstate) +{ + *tstate = (TryState) { + .trylevel = trylevel, + .got_int = got_int, + .did_throw = did_throw, + .msg_list = (const struct msglist *const *)msg_list, + .private_msg_list = NULL, + }; + trylevel = 1; + got_int = false; + did_throw = false; + msg_list = &tstate->private_msg_list; +} + +/// End try block, set the error message if any and restore previous state +/// +/// @warning Return is consistent with most functions (false on error), not with +/// try_end (true on error). +/// +/// @param[in] tstate Previous state to restore. +/// @param[out] err Location where error should be saved. +/// +/// @return false if error occurred, true otherwise. +bool try_leave(const TryState *const tstate, Error *const err) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + const bool ret = !try_end(err); + assert(trylevel == 0); + assert(!got_int); + assert(!did_throw); + assert(msg_list == &tstate->private_msg_list); + assert(*msg_list == NULL); + trylevel = tstate->trylevel; + got_int = tstate->got_int; + did_throw = tstate->did_throw; + msg_list = (struct msglist **)tstate->msg_list; + return ret; +} + /// Start block that may cause vimscript exceptions void try_start(void) { diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index 159b9d5c2a..112d785bfd 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -82,6 +82,18 @@ #define api_free_window(value) #define api_free_tabpage(value) +/// Structure used for saving state for :try +/// +/// Used when caller is supposed to be operating when other VimL code is being +/// processed and that “other VimL code” must not be affected. +typedef struct { + int trylevel; + int got_int; + int did_throw; + struct msglist *private_msg_list; + const struct msglist *const *msg_list; +} TryState; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "api/private/helpers.h.generated.h" #endif -- cgit From e333957a1a9ae64b7daa36e08fd1df583114d4ba Mon Sep 17 00:00:00 2001 From: Matthieu Coudron Date: Mon, 3 Jul 2017 23:03:30 +0200 Subject: dict_get_value(): name the missing key (#6952) --- src/nvim/api/private/helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index d401ae52a0..1ed2bc013e 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -95,7 +95,7 @@ Object dict_get_value(dict_T *dict, String key, Error *err) dictitem_T *const di = tv_dict_find(dict, key.data, (ptrdiff_t)key.size); if (di == NULL) { - api_set_error(err, kErrorTypeValidation, "Key not found"); + api_set_error(err, kErrorTypeValidation, "Key '%s' not found", key.data); return (Object)OBJECT_INIT; } -- cgit From 78c5201234e478ff8f648adea95be18ca588a9cd Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 2 Jul 2017 04:54:24 +0200 Subject: 'cpoptions': remove "k" flag This was already removed in 3baba1e7bc66, except the documentation and CPO_VI entry. find_term_bykeys() is irrelevant to Nvim. --- src/nvim/api/vim.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 80efe86ea3..ac7c9cbce6 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -153,7 +153,6 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, char *ptr = NULL; // Set 'cpoptions' the way we want it. // FLAG_CPO_BSLASH set - backslashes are *not* treated specially - // FLAG_CPO_KEYCODE set - keycodes are *not* reverse-engineered // FLAG_CPO_SPECI unset - sequences *are* interpreted // The third from end parameter of replace_termcodes() is true so that the // sequence is recognised - needed for a real backslash. -- cgit From 0ea7e45bc1d1881f505da2b77e0b3e4eb56f12fe Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 2 Jul 2017 13:21:38 +0200 Subject: 'cpoptions': remove "<" flag; ignore Closes #6937 "nvim_get_keymap output is unreliable" --- src/nvim/api/vim.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index ac7c9cbce6..8ab0c0ebda 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -136,9 +136,13 @@ Integer nvim_input(String keys) return (Integer)input_enqueue(keys); } -/// Replaces terminal codes and key codes (, , ...) in a string with +/// Replaces terminal codes and |keycodes| (, , ...) in a string with /// the internal representation. /// +/// @param str String to be converted. +/// @param from_part Legacy Vim parameter. Usually true. +/// @param do_lt Also translate . Does nothing if `special` is false. +/// @param special Replace |keycodes|, e.g. becomes a "\n" char. /// @see replace_termcodes /// @see cpoptions String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, @@ -151,11 +155,6 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, } char *ptr = NULL; - // Set 'cpoptions' the way we want it. - // FLAG_CPO_BSLASH set - backslashes are *not* treated specially - // FLAG_CPO_SPECI unset - sequences *are* interpreted - // The third from end parameter of replace_termcodes() is true so that the - // sequence is recognised - needed for a real backslash. replace_termcodes((char_u *)str.data, str.size, (char_u **)&ptr, from_part, do_lt, special, CPO_TO_CPO_FLAGS); return cstr_as_string(ptr); -- cgit From 0b88bf256d629cfe53c94896e140511e7f312b25 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 2 Jul 2017 13:46:41 +0200 Subject: doc: api.txt; deprecate --- src/nvim/api/vim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 8ab0c0ebda..2bc31b2812 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -141,7 +141,7 @@ Integer nvim_input(String keys) /// /// @param str String to be converted. /// @param from_part Legacy Vim parameter. Usually true. -/// @param do_lt Also translate . Does nothing if `special` is false. +/// @param do_lt Also translate . Ignored if `special` is false. /// @param special Replace |keycodes|, e.g. becomes a "\n" char. /// @see replace_termcodes /// @see cpoptions -- cgit From 2a6423eba732b005e277bac393f2246308dcc378 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 16 Jul 2017 22:03:31 +0300 Subject: api helpers: Save/restore more values in try_enter/try_leave This fixes memory leak reported by ASAN. This also somehow fixes test40, though I have no idea why except that that test yields memory leak report. --- src/nvim/api/private/helpers.c | 9 +++++++++ src/nvim/api/private/helpers.h | 3 +++ 2 files changed, 12 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index a04cc9a312..6ff56709cd 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -49,13 +49,17 @@ void try_enter(TryState *const tstate) .trylevel = trylevel, .got_int = got_int, .did_throw = did_throw, + .need_rethrow = need_rethrow, + .current_exception = current_exception, .msg_list = (const struct msglist *const *)msg_list, .private_msg_list = NULL, }; trylevel = 1; got_int = false; did_throw = false; + need_rethrow = false; msg_list = &tstate->private_msg_list; + current_exception = NULL; } /// End try block, set the error message if any and restore previous state @@ -72,14 +76,17 @@ bool try_leave(const TryState *const tstate, Error *const err) { const bool ret = !try_end(err); assert(trylevel == 0); + assert(!need_rethrow); assert(!got_int); assert(!did_throw); assert(msg_list == &tstate->private_msg_list); assert(*msg_list == NULL); + assert(current_exception == NULL); trylevel = tstate->trylevel; got_int = tstate->got_int; did_throw = tstate->did_throw; msg_list = (struct msglist **)tstate->msg_list; + current_exception = tstate->current_exception; return ret; } @@ -96,6 +103,8 @@ void try_start(void) /// @return true if an error occurred bool try_end(Error *err) { + // Note: all globals manipulated here should be saved/restored in + // try_enter/try_leave. --trylevel; // Without this it stops processing all subsequent VimL commands and diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index 112d785bfd..0b2cf883a6 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -6,6 +6,7 @@ #include "nvim/api/private/defs.h" #include "nvim/vim.h" #include "nvim/memory.h" +#include "nvim/ex_eval.h" #include "nvim/lib/kvec.h" #define OBJECT_OBJ(o) o @@ -90,6 +91,8 @@ typedef struct { int trylevel; int got_int; int did_throw; + int need_rethrow; + except_T *current_exception; struct msglist *private_msg_list; const struct msglist *const *msg_list; } TryState; -- cgit From cfb1d937a64fcec836fdf26d6ea67024aeafabeb Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 18 Jul 2017 00:08:57 +0300 Subject: api helpers: Also save and restore did_emsg --- src/nvim/api/private/helpers.c | 19 ++++++++++++------- src/nvim/api/private/helpers.h | 7 ++++--- 2 files changed, 16 insertions(+), 10 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 6ff56709cd..b6ecc319c1 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -46,20 +46,22 @@ typedef struct { void try_enter(TryState *const tstate) { *tstate = (TryState) { + .current_exception = current_exception, + .msg_list = (const struct msglist *const *)msg_list, + .private_msg_list = NULL, .trylevel = trylevel, .got_int = got_int, .did_throw = did_throw, .need_rethrow = need_rethrow, - .current_exception = current_exception, - .msg_list = (const struct msglist *const *)msg_list, - .private_msg_list = NULL, + .did_emsg = did_emsg, }; + msg_list = &tstate->private_msg_list; + current_exception = NULL; trylevel = 1; got_int = false; did_throw = false; need_rethrow = false; - msg_list = &tstate->private_msg_list; - current_exception = NULL; + did_emsg = false; } /// End try block, set the error message if any and restore previous state @@ -79,14 +81,17 @@ bool try_leave(const TryState *const tstate, Error *const err) assert(!need_rethrow); assert(!got_int); assert(!did_throw); + assert(!did_emsg); assert(msg_list == &tstate->private_msg_list); assert(*msg_list == NULL); assert(current_exception == NULL); + msg_list = (struct msglist **)tstate->msg_list; + current_exception = tstate->current_exception; trylevel = tstate->trylevel; got_int = tstate->got_int; did_throw = tstate->did_throw; - msg_list = (struct msglist **)tstate->msg_list; - current_exception = tstate->current_exception; + need_rethrow = tstate->need_rethrow; + did_emsg = tstate->did_emsg; return ret; } diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index 0b2cf883a6..87f334ac30 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -88,13 +88,14 @@ /// Used when caller is supposed to be operating when other VimL code is being /// processed and that “other VimL code” must not be affected. typedef struct { + except_T *current_exception; + struct msglist *private_msg_list; + const struct msglist *const *msg_list; int trylevel; int got_int; int did_throw; int need_rethrow; - except_T *current_exception; - struct msglist *private_msg_list; - const struct msglist *const *msg_list; + int did_emsg; } TryState; #ifdef INCLUDE_GENERATED_DECLARATIONS -- cgit From 25c6ac1af63c0d68b7993910e94d3b0f1b8bbfd7 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 18 Jul 2017 01:21:23 +0300 Subject: *: Fix clint errors --- src/nvim/api/private/helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index b6ecc319c1..cdaceddc11 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -110,7 +110,7 @@ bool try_end(Error *err) { // Note: all globals manipulated here should be saved/restored in // try_enter/try_leave. - --trylevel; + trylevel--; // Without this it stops processing all subsequent VimL commands and // generates strange error messages if I e.g. try calling Test() in a -- cgit From 4d8ff5ec012cd517cf8010144f158d6f5c96d5bb Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 6 Aug 2017 14:38:54 +0300 Subject: api/helpers: Clarify try_start() usage --- src/nvim/api/private/helpers.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index cdaceddc11..021d1d43ff 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -96,6 +96,13 @@ bool try_leave(const TryState *const tstate, Error *const err) } /// Start block that may cause vimscript exceptions +/// +/// Each try_start() call should be mirrorred by try_end() call. +/// +/// To be used as a replacement of `:try … catch … endtry` in C code, in cases +/// when error flag could not already be set. If there may be pending error +/// state at the time try_start() is executed which needs to be preserved, +/// try_enter()/try_leave() pair should be used instead. void try_start(void) { ++trylevel; -- cgit From 36acfce4eac9dd131a39c4dbdff2836ab3e21d73 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 6 Aug 2017 15:23:05 +0300 Subject: api/helpers: Fix typo --- src/nvim/api/private/helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 021d1d43ff..e736e29e2d 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -97,7 +97,7 @@ bool try_leave(const TryState *const tstate, Error *const err) /// Start block that may cause vimscript exceptions /// -/// Each try_start() call should be mirrorred by try_end() call. +/// Each try_start() call should be mirrored by try_end() call. /// /// To be used as a replacement of `:try … catch … endtry` in C code, in cases /// when error flag could not already be set. If there may be pending error -- cgit From b13070ec01844977f10cae38fc6f2a0fd9defad8 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 17 Aug 2017 23:30:28 +0200 Subject: doc/api: nvim_out_write() and friends References #7178 --- src/nvim/api/vim.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 2bc31b2812..cfbe34b848 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -484,7 +484,8 @@ void nvim_set_option(String name, Object value, Error *err) set_option_to(NULL, SREQ_GLOBAL, name, value, err); } -/// Writes a message to vim output buffer +/// Writes a message to the Vim output buffer. Does not append "\n", the +/// message is buffered (won't display) until a linefeed is written. /// /// @param str Message void nvim_out_write(String str) @@ -493,7 +494,8 @@ void nvim_out_write(String str) write_msg(str, false); } -/// Writes a message to vim error buffer +/// Writes a message to the Vim error buffer. Does not append "\n", the +/// message is buffered (won't display) until a linefeed is written. /// /// @param str Message void nvim_err_write(String str) @@ -502,8 +504,8 @@ void nvim_err_write(String str) write_msg(str, true); } -/// Writes a message to vim error buffer. Appends a linefeed to ensure all -/// contents are written. +/// Writes a message to the Vim error buffer. Appends "\n", so the buffer is +/// flushed (and displayed). /// /// @param str Message /// @see nvim_err_write() -- cgit From cdd9e868efdad1f1eb9febfabb5f8671e75b95b9 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 2 Sep 2017 19:51:49 +0200 Subject: doc: channel, eventloop --- src/nvim/api/ui.c | 1 + src/nvim/api/vim.c | 28 ++++++++-------------------- 2 files changed, 9 insertions(+), 20 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 573be23d8e..bbbd5ab2dc 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -215,6 +215,7 @@ static void ui_set_option(UI *ui, String name, Object value, Error *error) #undef UI_EXT_OPTION } +/// Pushes data into UI.UIData, to be consumed later by remote_ui_flush(). static void push_call(UI *ui, char *name, Array args) { Array call = ARRAY_DICT_INIT; diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index cfbe34b848..ab893a4c0f 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -255,12 +255,11 @@ free_vim_args: return rv; } -/// Execute lua code. Parameters might be passed, they are available inside -/// the chunk as `...`. The chunk can return a value. +/// Execute lua code. Parameters (if any) are available as `...` inside the +/// chunk. The chunk can return a value. /// -/// To evaluate an expression, it must be prefixed with "return ". For -/// instance, to call a lua function with arguments sent in and get its -/// return value back, use the code "return my_function(...)". +/// Only statements are executed. To evaluate an expression, prefix it +/// with `return`: return my_function(...) /// /// @param code lua code to execute /// @param args Arguments to the code @@ -423,29 +422,18 @@ void nvim_del_var(String name, Error *err) dict_set_var(&globvardict, name, NIL, true, false, err); } -/// Sets a global variable -/// /// @deprecated -/// -/// @param name Variable name -/// @param value Variable value -/// @param[out] err Error details, if any +/// @see nvim_set_var /// @return Old value or nil if there was no previous value. -/// -/// @warning It may return nil if there was no previous value -/// or if previous value was `v:null`. +/// @warning May return nil if there was no previous value +/// OR if previous value was `v:null`. Object vim_set_var(String name, Object value, Error *err) { return dict_set_var(&globvardict, name, value, false, true, err); } -/// Removes a global variable -/// /// @deprecated -/// -/// @param name Variable name -/// @param[out] err Error details, if any -/// @return Old value +/// @see nvim_del_var Object vim_del_var(String name, Error *err) { return dict_set_var(&globvardict, name, NIL, true, true, err); -- cgit From ba7277cfb4e2556f246446d06b53f3427f28130f Mon Sep 17 00:00:00 2001 From: Matthieu Coudron Date: Wed, 26 Jul 2017 23:28:26 +0200 Subject: Adds nvim_get_hl_by_name/by_id ...in order to retrieve highlights. Added test/functional/api/highlight_spec.lua HL_NORMAL is not really a good name, since it's more like an empty attribute than the normal's one. If one pays attention, syn_cterm_attr2entry is never called with attr=0 because it's always special cased before. I suggest in subsequent PRs we remove the ATTR_OFF and just insert an EMPTY ATTR/RESET_ATTR/UNINITIALIZED for id 0. --- src/nvim/api/ui.c | 34 +--------------------------------- src/nvim/api/vim.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 33 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index bbbd5ab2dc..afbee09c1c 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -242,39 +242,7 @@ static void push_call(UI *ui, char *name, Array args) static void remote_ui_highlight_set(UI *ui, HlAttrs attrs) { Array args = ARRAY_DICT_INIT; - Dictionary hl = ARRAY_DICT_INIT; - - if (attrs.bold) { - PUT(hl, "bold", BOOLEAN_OBJ(true)); - } - - if (attrs.underline) { - PUT(hl, "underline", BOOLEAN_OBJ(true)); - } - - if (attrs.undercurl) { - PUT(hl, "undercurl", BOOLEAN_OBJ(true)); - } - - if (attrs.italic) { - PUT(hl, "italic", BOOLEAN_OBJ(true)); - } - - if (attrs.reverse) { - PUT(hl, "reverse", BOOLEAN_OBJ(true)); - } - - if (attrs.foreground != -1) { - PUT(hl, "foreground", INTEGER_OBJ(attrs.foreground)); - } - - if (attrs.background != -1) { - PUT(hl, "background", INTEGER_OBJ(attrs.background)); - } - - if (attrs.special != -1) { - PUT(hl, "special", INTEGER_OBJ(attrs.special)); - } + Dictionary hl = hlattrs2dict(attrs); ADD(args, DICTIONARY_OBJ(hl)); push_call(ui, "highlight_set", args); diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index ab893a4c0f..0459d9235d 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -33,6 +33,7 @@ #include "nvim/syntax.h" #include "nvim/getchar.h" #include "nvim/os/input.h" +#include "nvim/ui.h" #define LINE_BUFFER_SIZE 4096 @@ -55,6 +56,42 @@ void nvim_command(String command, Error *err) try_end(err); } +/// Retrieves highlight description from its name +/// +/// @param name Highlight group name +/// @return a highlight description e.g. {'bold': true, 'bg': 123, 'fg': 42} +/// @see nvim_get_hl_by_id +Dictionary nvim_get_hl_by_name(String name, Error *err) + FUNC_API_SINCE(3) +{ + Dictionary result = ARRAY_DICT_INIT; + int id = syn_name2id((const char_u *)name.data); + + if (id == 0) { + api_set_error(err, kErrorTypeException, "Invalid highlight name %s", + name.data); + return result; + } + result = nvim_get_hl_by_id(id, err); + return result; +} + +/// Retrieves highlight description from its id +/// +/// @param hl_id highlight id as returned by hlID() +/// @see nvim_get_hl_by_name +Dictionary nvim_get_hl_by_id(Integer hl_id, Error *err) + FUNC_API_SINCE(3) +{ + Dictionary dic = ARRAY_DICT_INIT; + if (syn_get_final_id((int)hl_id) == 0) { + api_set_error(err, kErrorTypeException, "Invalid highlight id %d", hl_id); + return dic; + } + int attrcode = syn_id2attr((int)hl_id); + return get_attr_by_id(attrcode, err); +} + /// Passes input keys to Nvim. /// On VimL error: Does not fail, but updates v:errmsg. /// -- cgit From e3a2cca3878f44252eccdc1918cc8854145de860 Mon Sep 17 00:00:00 2001 From: Matthieu Coudron Date: Sun, 27 Aug 2017 00:33:36 +0200 Subject: Increased test coverage for RGB and cterm --- src/nvim/api/vim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 0459d9235d..bf3e4bc6a0 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -78,7 +78,7 @@ Dictionary nvim_get_hl_by_name(String name, Error *err) /// Retrieves highlight description from its id /// -/// @param hl_id highlight id as returned by hlID() +/// @param hl_id highlight id as returned by |hlID()| /// @see nvim_get_hl_by_name Dictionary nvim_get_hl_by_id(Integer hl_id, Error *err) FUNC_API_SINCE(3) @@ -89,7 +89,7 @@ Dictionary nvim_get_hl_by_id(Integer hl_id, Error *err) return dic; } int attrcode = syn_id2attr((int)hl_id); - return get_attr_by_id(attrcode, err); + return hl_get_attr_by_id(attrcode, err); } /// Passes input keys to Nvim. -- cgit From 3a006486397d611234abd9b429bce0b44d6b7747 Mon Sep 17 00:00:00 2001 From: Matthieu Coudron Date: Sun, 3 Sep 2017 05:25:57 +0200 Subject: Changed prototypes to accept a boolean "rgb" --- src/nvim/api/vim.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index bf3e4bc6a0..0c3c497533 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -59,9 +59,10 @@ void nvim_command(String command, Error *err) /// Retrieves highlight description from its name /// /// @param name Highlight group name +/// @param rgb True to export GUI values /// @return a highlight description e.g. {'bold': true, 'bg': 123, 'fg': 42} /// @see nvim_get_hl_by_id -Dictionary nvim_get_hl_by_name(String name, Error *err) +Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Error *err) FUNC_API_SINCE(3) { Dictionary result = ARRAY_DICT_INIT; @@ -72,15 +73,16 @@ Dictionary nvim_get_hl_by_name(String name, Error *err) name.data); return result; } - result = nvim_get_hl_by_id(id, err); + result = nvim_get_hl_by_id(id, rgb, err); return result; } /// Retrieves highlight description from its id /// /// @param hl_id highlight id as returned by |hlID()| +/// @param rgb True to export GUI values /// @see nvim_get_hl_by_name -Dictionary nvim_get_hl_by_id(Integer hl_id, Error *err) +Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Error *err) FUNC_API_SINCE(3) { Dictionary dic = ARRAY_DICT_INIT; @@ -89,7 +91,7 @@ Dictionary nvim_get_hl_by_id(Integer hl_id, Error *err) return dic; } int attrcode = syn_id2attr((int)hl_id); - return hl_get_attr_by_id(attrcode, err); + return hl_get_attr_by_id(attrcode, rgb, err); } /// Passes input keys to Nvim. -- cgit From 52517321d1859c31fef14aa75d784615693fcecb Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 8 Oct 2017 20:23:11 +0200 Subject: test: nvim_get_hl_by_name/by_id #7082 - test all properties - test failure modes --- src/nvim/api/vim.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index bc89ffefe6..98f4410347 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -33,7 +33,6 @@ #include "nvim/syntax.h" #include "nvim/getchar.h" #include "nvim/os/input.h" -#include "nvim/ui.h" #define LINE_BUFFER_SIZE 4096 -- cgit From dfe806ea8b90ace9ef2ee63aafbf10ebea2df7ef Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Thu, 19 Oct 2017 11:46:07 +0200 Subject: bufhl: support creating new groups --- src/nvim/api/buffer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 82de8fd4a2..c381e92dc7 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -793,7 +793,11 @@ Integer nvim_buf_add_highlight(Buffer buffer, col_end = MAXCOL; } - int hlg_id = syn_name2id((char_u *)(hl_group.data ? hl_group.data : "")); + int hlg_id = 0; + if (hl_group.size > 0) { + hlg_id = syn_check_group((char_u *)hl_group.data, (int)hl_group.size); + } + src_id = bufhl_add_hl(buf, (int)src_id, hlg_id, (linenr_T)line+1, (colnr_T)col_start+1, (colnr_T)col_end); return src_id; -- cgit From ab85999eb7c53e9d2b5bca5f8896ea11cb1df13e Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Thu, 11 May 2017 07:11:21 +0100 Subject: ext_cmdline: change to use ui_call --- src/nvim/api/ui_events.in.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index 1b5d17584f..093251bb00 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -68,4 +68,15 @@ void popupmenu_select(Integer selected) void tabline_update(Tabpage current, Array tabs) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void cmdline_enter(void) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void cmdline_show(Array content, Integer pos, String firstc, String prompt) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void cmdline_pos(Integer pos) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void cmdline_char(String c, Integer shift) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void cmdline_hide(void) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; + #endif // NVIM_API_UI_EVENTS_IN_H -- cgit From 866dadaf753ba3733feb8c22d7da47af757bd35c Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Thu, 11 May 2017 07:51:10 +0100 Subject: ext_cmdline: added cmdline level add cchar_to_string --- src/nvim/api/private/helpers.c | 16 ++++++++++++++++ src/nvim/api/ui_events.in.h | 11 ++++------- 2 files changed, 20 insertions(+), 7 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index e736e29e2d..f00fbf69ea 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -667,6 +667,22 @@ tabpage_T *find_tab_by_handle(Tabpage tabpage, Error *err) return rv; } +/// Allocates a String consisting of a single char. Does not support multibyte +/// characters. The resulting string is also NUL-terminated, to facilitate +/// interoperating with code using C strings. +/// +/// @param char the char to convert +/// @return the resulting String, if the input char was NUL, an +/// empty String is returned +String cchar_to_string(char c) +{ + char buf[] = { c, NUL }; + return (String) { + .data = xmemdupz(buf, 1), + .size = (c != NUL) ? 1 : 0 + }; +} + /// Copies a C string into a String (binary safe string, characters + length). /// The resulting string is also NUL-terminated, to facilitate interoperating /// with code using C strings. diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index 093251bb00..17eefbe1d6 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -66,17 +66,14 @@ void popupmenu_hide(void) void popupmenu_select(Integer selected) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void tabline_update(Tabpage current, Array tabs) - FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; - -void cmdline_enter(void) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; -void cmdline_show(Array content, Integer pos, String firstc, String prompt) +void cmdline_show(Array content, Integer pos, String firstc, String prompt, Integer level) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; -void cmdline_pos(Integer pos) +void cmdline_pos(Integer pos, Integer level) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; -void cmdline_char(String c, Integer shift) +void cmdline_char(String c, Integer shift, Integer level) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; -void cmdline_hide(void) +void cmdline_hide(Integer level) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; #endif // NVIM_API_UI_EVENTS_IN_H -- cgit From 461ae698242458bffbf5fb68de89fe8b2a3defd2 Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Mon, 26 Jun 2017 11:19:40 +0100 Subject: ext_cmdline: Add function block support --- src/nvim/api/ui_events.in.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index 17eefbe1d6..5602dc6df3 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -75,5 +75,9 @@ void cmdline_char(String c, Integer shift, Integer level) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void cmdline_hide(Integer level) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void cmdline_function_show(void) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void cmdline_function_hide(void) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; #endif // NVIM_API_UI_EVENTS_IN_H -- cgit From fb389a6b4b1e6fedb559dc2e5845dd138e8ff264 Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Mon, 26 Jun 2017 15:27:49 +0100 Subject: ext_cmdline: added indent --- src/nvim/api/ui_events.in.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index 5602dc6df3..700d99dc6b 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -67,7 +67,7 @@ void popupmenu_select(Integer selected) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void tabline_update(Tabpage current, Array tabs) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; -void cmdline_show(Array content, Integer pos, String firstc, String prompt, Integer level) +void cmdline_show(Array content, Integer pos, String firstc, String prompt, Integer indent, Integer level) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void cmdline_pos(Integer pos, Integer level) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; -- cgit From 5ad591ef2d0ef184f78c728b1774c2a55fe2e581 Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Tue, 27 Jun 2017 02:20:27 +0100 Subject: ext_cmdline: lint --- src/nvim/api/ui_events.in.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index 700d99dc6b..bb1084c838 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -66,18 +66,19 @@ void popupmenu_hide(void) void popupmenu_select(Integer selected) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void tabline_update(Tabpage current, Array tabs) - FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; -void cmdline_show(Array content, Integer pos, String firstc, String prompt, Integer indent, Integer level) - FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void cmdline_show(Array content, Integer pos, String firstc, String prompt, + Integer indent, Integer level) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void cmdline_pos(Integer pos, Integer level) - FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void cmdline_char(String c, Integer shift, Integer level) - FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void cmdline_hide(Integer level) - FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void cmdline_function_show(void) - FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void cmdline_function_hide(void) - FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; #endif // NVIM_API_UI_EVENTS_IN_H -- cgit From 22402fb99d05191cf140293cfb5f67902e78a8a8 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 16 Aug 2017 12:19:29 +0200 Subject: ext_cmdline: add support for highlighting --- src/nvim/api/private/helpers.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index f00fbf69ea..2944925a9c 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -703,6 +703,23 @@ String cstr_to_string(const char *str) }; } +/// Copies buffer to an allocated String. +/// The resulting string is also NUL-terminated, to facilitate interoperating +/// with code using C strings. +/// +/// @param buf the buffer to copy +/// @param size length of the buffer +/// @return the resulting String, if the input string was NULL, an +/// empty String is returned +String cbuf_to_string(const char *buf, size_t size) + FUNC_ATTR_NONNULL_ALL +{ + return (String) { + .data = xmemdupz(buf, size), + .size = size + }; +} + /// Creates a String using the given C string. Unlike /// cstr_to_string this function DOES NOT copy the C string. /// -- cgit From a68817f56517a31943806bd0b5a0030cdd35e182 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 16 Aug 2017 13:57:58 +0200 Subject: ext_cmdline: extend "function" to generic "block" mechanism --- src/nvim/api/ui_events.in.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index bb1084c838..764078c6bd 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -67,6 +67,7 @@ void popupmenu_select(Integer selected) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void tabline_update(Tabpage current, Array tabs) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; + void cmdline_show(Array content, Integer pos, String firstc, String prompt, Integer indent, Integer level) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; @@ -76,9 +77,11 @@ void cmdline_char(String c, Integer shift, Integer level) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void cmdline_hide(Integer level) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; -void cmdline_function_show(void) +void cmdline_block_show(Array lines) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void cmdline_block_append(Array lines) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; -void cmdline_function_hide(void) +void cmdline_block_hide(void) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; #endif // NVIM_API_UI_EVENTS_IN_H -- cgit From f2aaa4ae8b84f74666b4379b391f333f34868a45 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 16 Aug 2017 15:38:12 +0200 Subject: ext_cmdline: rename cmdline_char to cmdline_special_char --- src/nvim/api/ui_events.in.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index 764078c6bd..65357d008a 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -73,7 +73,7 @@ void cmdline_show(Array content, Integer pos, String firstc, String prompt, FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void cmdline_pos(Integer pos, Integer level) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; -void cmdline_char(String c, Integer shift, Integer level) +void cmdline_special_char(String c, Boolean shift, Integer level) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void cmdline_hide(Integer level) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; -- cgit From 39e83fa7cb4486d30f788c3b27594d106d5e76ab Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Fri, 24 Feb 2017 06:12:34 +0000 Subject: ui: allow external ui to draw wildmenu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Björn Linse Updated docs and tests. --- src/nvim/api/ui_events.in.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index 65357d008a..579ba1441a 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -65,6 +65,7 @@ void popupmenu_hide(void) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void popupmenu_select(Integer selected) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; + void tabline_update(Tabpage current, Array tabs) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; @@ -84,4 +85,10 @@ void cmdline_block_append(Array lines) void cmdline_block_hide(void) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void wildmenu_show(Array content) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void wildmenu_select(Integer selected) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; +void wildmenu_hide(void) + FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; #endif // NVIM_API_UI_EVENTS_IN_H -- cgit From 22d161a5dd1c519f998916f45d61be92662fbb44 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 29 Oct 2017 20:11:44 +0300 Subject: api/vim: Add nvim_parse_expression function --- src/nvim/api/vim.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 98f4410347..9daa2fb398 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -886,6 +886,72 @@ theend: return rv; } +/// Parse a VimL expression +/// +/// @param[in] expr Expression to parse. Is always treated as a single line. +/// @param[in] flags Flags: "m" if multiple expressions in a row are allowed +/// (only the first one will be parsed), "E" if EOC tokens +/// are not allowed (determines whether they will stop +/// parsing process or be recognized as an operator/space, +/// though also yielding an error). +/// +/// Use only "m" to parse like for "=", only "E" to +/// parse like for ":echo", empty string for ":let". +/// +/// @return AST: top-level dectionary holds keys +/// +/// "error": Dictionary with error, present only if parser saw some +/// error. Contains the following keys: +/// +/// "message": String, error message in printf format, translated. +/// Must contain exactly one "%.*s". +/// "arg": String, error message argument. +/// +/// "ast": actual AST, a dictionary with the following keys: +/// +/// "type": node type, one of the value names from ExprASTNodeType +/// stringified without "kExprNode" prefix. +/// "start": a pair [line, column] describing where node is “started” +/// where "line" is always 0 (will not be 0 if you will be +/// using nvim_parse_viml() on e.g. ":let", but that is not +/// present yet). Both elements are Integers. +/// "len": “length” of the node. This and "start" are there for +/// debugging purposes primary (debugging parser and providing +/// debug information). +/// "children": a list of nodes described in top/"ast". There always +/// is zero, one or two children, key will contain an +/// empty array if node can have children, but has no and +/// will not be present at all if node can’t have any +/// children. Maximum number of children may be found in +/// node_maxchildren array. +/// +/// Local values (present only for certain nodes): +/// +/// "scope": a single Integer, specifies scope for "Option" and +/// "PlainIdentifier" nodes. For "Option" it is one of +/// ExprOptScope values, for "PlainIdentifier" it is one of +/// ExprVarScope values. +/// "ident": identifier (without scope, if any), present for "Option", +/// "PlainIdentifier", "PlainKey" and "Environment" nodes. +/// "name": Integer, register name (one character) or -1. Only present +/// for "Register" nodes. +/// "cmp_type": String, comparison type, one of the value names from +/// ExprComparisonType, stringified without "kExprCmp" +/// prefix. Only present for "Comparison" nodes. +/// "ccs_strategy": String, case comparison strategy, one of the +/// value names from ExprCaseCompareStrategy, +/// stringified without "kCCStrategy" prefix. Only +/// present for "Comparison" nodes. +/// "ivalue": Integer, integer value for "Integer" nodes. +/// "fvalue": Float, floating-point value for "Float" nodes. +/// "svalue": String, value for "SingleQuotedString" and +/// "DoubleQuotedString" nodes. +Dictionary nvim_parse_expression(String expr, String flags, Error *err) + FUNC_API_SINCE(4) +{ + return (Dictionary)ARRAY_DICT_INIT; +} + /// Writes a message to vim output or error buffer. The string is split /// and flushed after each newline. Incomplete lines are kept for writing -- cgit From b9d5aea073521f3278bea257be306b7ac2b8d83c Mon Sep 17 00:00:00 2001 From: ZyX Date: Fri, 3 Nov 2017 11:38:59 +0300 Subject: api/vim: Create part of nvim_parse_expression function --- src/nvim/api/vim.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 9daa2fb398..446a049897 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -33,6 +33,8 @@ #include "nvim/syntax.h" #include "nvim/getchar.h" #include "nvim/os/input.h" +#include "nvim/viml/parser/expressions.h" +#include "nvim/viml/parser/parser.h" #define LINE_BUFFER_SIZE 4096 @@ -897,6 +899,12 @@ theend: /// /// Use only "m" to parse like for "=", only "E" to /// parse like for ":echo", empty string for ":let". +/// @param[in] highlight If true, return value will also include "highlight" +/// key containing array of 4-tuples (arrays) (Integer, +/// Integer, Integer, String), where first three numbers +/// define the highlighted region and represent line, +/// starting column and ending column (latter exclusive: +/// one should highlight region [start_col, end_col)). /// /// @return AST: top-level dectionary holds keys /// @@ -946,9 +954,105 @@ theend: /// "fvalue": Float, floating-point value for "Float" nodes. /// "svalue": String, value for "SingleQuotedString" and /// "DoubleQuotedString" nodes. -Dictionary nvim_parse_expression(String expr, String flags, Error *err) +Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, + Error *err) FUNC_API_SINCE(4) { + int pflags = 0; + for (size_t i = 0 ; i < flags.size ; i++) { + switch (flags.data[i]) { + case 'm': { pflags |= kExprFlagsMulti; break; } + case 'E': { pflags |= kExprFlagsDisallowEOC; break; } + default: { + api_set_error(err, kErrorTypeValidation, "Invalid flag: '%c' (%u)", + flags.data[i], (unsigned)flags.data[i]); + return (Dictionary)ARRAY_DICT_INIT; + } + } + } + ParserLine plines[] = { + { + .data = expr.data, + .size = expr.size, + .allocated = false, + }, + { NULL, 0, false }, + }; + ParserLine *plines_p = plines; + ParserHighlight colors; + kvi_init(colors); + ParserHighlight *const colors_p = (highlight ? &colors : NULL); + ParserState pstate; + viml_parser_init( + &pstate, parser_simple_get_line, &plines_p, colors_p); + ExprAST east = viml_pexpr_parse(&pstate, pflags); + + const size_t dict_size = ( + 1 // "ast" + + (size_t)(east.err.arg != NULL) // "error" + + (size_t)highlight // "highlight" + ); + Dictionary ret = { + .items = xmalloc(dict_size * sizeof(ret.items[0])), + .size = 0, + .capacity = dict_size, + }; + ret.items[ret.size++] = (KeyValuePair) { + .key = STATIC_CSTR_AS_STRING("ast"), + .value = NIL, + }; + if (east.err.arg != NULL) { + Dictionary err_dict = { + .items = xmalloc(2 * sizeof(err_dict.items[0])), + .size = 2, + .capacity = 2, + }; + err_dict.items[0] = (KeyValuePair) { + .key = STATIC_CSTR_AS_STRING("message"), + .value = STRING_OBJ(cstr_to_string(east.err.arg)), + }; + err_dict.items[1] = (KeyValuePair) { + .key = STATIC_CSTR_AS_STRING("arg"), + .value = STRING_OBJ(((String) { + .data = xmemdup(east.err.arg, (size_t)east.err.arg_len), + .size = (size_t)east.err.arg_len, + })), + }; + ret.items[ret.size++] = (KeyValuePair) { + .key = STATIC_CSTR_AS_STRING("error"), + .value = DICTIONARY_OBJ(err_dict), + }; + } + if (highlight) { + Array hl = (Array) { + .items = xmalloc(kv_size(colors) * sizeof(hl.items[0])), + .capacity = kv_size(colors), + .size = kv_size(colors), + }; + for (size_t i = 0 ; i < kv_size(colors) ; i++) { + const ParserHighlightChunk chunk = kv_A(colors, i); + Array chunk_arr = (Array) { + .items = xmalloc(4), + .capacity = 4, + .size = 4, + }; + chunk_arr.items[0] = INTEGER_OBJ((Integer)chunk.start.line); + chunk_arr.items[1] = INTEGER_OBJ((Integer)chunk.start.col); + chunk_arr.items[2] = INTEGER_OBJ((Integer)chunk.end_col); + chunk_arr.items[3] = STRING_OBJ(cstr_to_string(chunk.group)); + hl.items[i] = ARRAY_OBJ(chunk_arr); + } + ret.items[ret.size++] = (KeyValuePair) { + .key = STATIC_CSTR_AS_STRING("highlight"), + .value = ARRAY_OBJ(hl), + }; + } + + // FIXME: populate AST + + assert(ret.size == ret.capacity); + viml_pexpr_free_ast(east); + viml_parser_destroy(&pstate); return (Dictionary)ARRAY_DICT_INIT; } -- cgit From 07ec709141886c6db4f944665e07a36ef7302eb4 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 5 Nov 2017 01:33:44 +0300 Subject: vim/api: Actually dump AST, fix some bugs in nvim_parse_expression --- src/nvim/api/vim.c | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 249 insertions(+), 15 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 446a049897..1aab87010e 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -888,6 +888,13 @@ theend: return rv; } +typedef struct { + ExprASTNode **node_p; + Object *ret_node_p; +} ExprASTConvStackItem; + +typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; + /// Parse a VimL expression /// /// @param[in] expr Expression to parse. Is always treated as a single line. @@ -915,7 +922,8 @@ theend: /// Must contain exactly one "%.*s". /// "arg": String, error message argument. /// -/// "ast": actual AST, a dictionary with the following keys: +/// "ast": actual AST, either nil or a dictionary with the following +/// keys: /// /// "type": node type, one of the value names from ExprASTNodeType /// stringified without "kExprNode" prefix. @@ -927,11 +935,9 @@ theend: /// debugging purposes primary (debugging parser and providing /// debug information). /// "children": a list of nodes described in top/"ast". There always -/// is zero, one or two children, key will contain an -/// empty array if node can have children, but has no and -/// will not be present at all if node can’t have any -/// children. Maximum number of children may be found in -/// node_maxchildren array. +/// is zero, one or two children, key will not be present +/// if node has no children. Maximum number of children +/// may be found in node_maxchildren array. /// /// Local values (present only for certain nodes): /// @@ -950,6 +956,8 @@ theend: /// value names from ExprCaseCompareStrategy, /// stringified without "kCCStrategy" prefix. Only /// present for "Comparison" nodes. +/// "invert": Boolean, true if result of comparison needs to be +/// inverted. Only present for "Comparison" nodes. /// "ivalue": Integer, integer value for "Integer" nodes. /// "fvalue": Float, floating-point value for "Float" nodes. /// "svalue": String, value for "SingleQuotedString" and @@ -998,7 +1006,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, .capacity = dict_size, }; ret.items[ret.size++] = (KeyValuePair) { - .key = STATIC_CSTR_AS_STRING("ast"), + .key = STATIC_CSTR_TO_STRING("ast"), .value = NIL, }; if (east.err.arg != NULL) { @@ -1008,18 +1016,18 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, .capacity = 2, }; err_dict.items[0] = (KeyValuePair) { - .key = STATIC_CSTR_AS_STRING("message"), + .key = STATIC_CSTR_TO_STRING("message"), .value = STRING_OBJ(cstr_to_string(east.err.arg)), }; err_dict.items[1] = (KeyValuePair) { - .key = STATIC_CSTR_AS_STRING("arg"), + .key = STATIC_CSTR_TO_STRING("arg"), .value = STRING_OBJ(((String) { - .data = xmemdup(east.err.arg, (size_t)east.err.arg_len), + .data = xmemdupz(east.err.arg, (size_t)east.err.arg_len), .size = (size_t)east.err.arg_len, })), }; ret.items[ret.size++] = (KeyValuePair) { - .key = STATIC_CSTR_AS_STRING("error"), + .key = STATIC_CSTR_TO_STRING("error"), .value = DICTIONARY_OBJ(err_dict), }; } @@ -1032,7 +1040,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, for (size_t i = 0 ; i < kv_size(colors) ; i++) { const ParserHighlightChunk chunk = kv_A(colors, i); Array chunk_arr = (Array) { - .items = xmalloc(4), + .items = xmalloc(4 * sizeof(chunk_arr.items[0])), .capacity = 4, .size = 4, }; @@ -1043,17 +1051,243 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, hl.items[i] = ARRAY_OBJ(chunk_arr); } ret.items[ret.size++] = (KeyValuePair) { - .key = STATIC_CSTR_AS_STRING("highlight"), + .key = STATIC_CSTR_TO_STRING("highlight"), .value = ARRAY_OBJ(hl), }; } - // FIXME: populate AST + // Walk over the AST, freeing nodes in process. + ExprASTConvStack ast_conv_stack; + kvi_init(ast_conv_stack); + kvi_push(ast_conv_stack, ((ExprASTConvStackItem) { + .node_p = &east.root, + .ret_node_p = &ret.items[0].value, + })); + while (kv_size(ast_conv_stack)) { + ExprASTConvStackItem cur_item = kv_last(ast_conv_stack); + if (*cur_item.node_p == NULL) { + assert(kv_size(ast_conv_stack) == 1); + kv_drop(ast_conv_stack, 1); + } else { + ExprASTNode *const node = *cur_item.node_p; + if (cur_item.ret_node_p->type == kObjectTypeNil) { + const size_t ret_node_items_size = (size_t)( + 3 // "type", "start" and "len" + + (node->children != NULL) // "children" + + (node->type == kExprNodeOption + || node->type == kExprNodePlainIdentifier) // "scope" + + (node->type == kExprNodeOption + || node->type == kExprNodePlainIdentifier + || node->type == kExprNodePlainKey + || node->type == kExprNodeEnvironment) // "ident" + + (node->type == kExprNodeRegister) // "name" + + (3 // "cmp_type", "ccs_strategy", "invert" + * (node->type == kExprNodeComparison)) + + (node->type == kExprNodeInteger) // "ivalue" + + (node->type == kExprNodeFloat) // "fvalue" + + (node->type == kExprNodeDoubleQuotedString + || node->type == kExprNodeSingleQuotedString) // "svalue" + + 0); + Dictionary ret_node = { + .items = xmalloc(ret_node_items_size * sizeof(ret_node.items[0])), + .capacity = ret_node_items_size, + .size = 0, + }; + *cur_item.ret_node_p = DICTIONARY_OBJ(ret_node); + } + Dictionary *ret_node = &cur_item.ret_node_p->data.dictionary; + if (node->children != NULL) { + const size_t num_children = 1 + (node->children->next != NULL); + Array children_array = { + .items = xmalloc(num_children * sizeof(children_array.items[0])), + .capacity = num_children, + .size = num_children, + }; + for (size_t i = 0; i < num_children; i++) { + children_array.items[i] = NIL; + } + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("children"), + .value = ARRAY_OBJ(children_array), + }; + kvi_push(ast_conv_stack, ((ExprASTConvStackItem) { + .node_p = &node->children, + .ret_node_p = &children_array.items[0], + })); + } else if (node->next != NULL) { + kvi_push(ast_conv_stack, ((ExprASTConvStackItem) { + .node_p = &node->children, + .ret_node_p = cur_item.ret_node_p + 1, + })); + } else if (node != NULL) { + kv_drop(ast_conv_stack, 1); + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("type"), + .value = STRING_OBJ(cstr_to_string(east_node_type_tab[node->type])), + }; + Array start_array = { + .items = xmalloc(2 * sizeof(start_array.items[0])), + .capacity = 2, + .size = 2, + }; + start_array.items[0] = INTEGER_OBJ((Integer)node->start.line); + start_array.items[1] = INTEGER_OBJ((Integer)node->start.col); + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("start"), + .value = ARRAY_OBJ(start_array), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("len"), + .value = INTEGER_OBJ((Integer)node->len), + }; + switch (node->type) { + case kExprNodeDoubleQuotedString: + case kExprNodeSingleQuotedString: { + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("svalue"), + .value = STRING_OBJ(cstr_as_string(node->data.str.value)), + }; + break; + } + case kExprNodeOption: { + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("scope"), + .value = INTEGER_OBJ(node->data.opt.scope), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ident"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(node->data.opt.ident, + node->data.opt.ident_len), + .size = node->data.opt.ident_len, + })), + }; + break; + } + case kExprNodePlainIdentifier: { + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("scope"), + .value = INTEGER_OBJ(node->data.var.scope), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ident"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(node->data.var.ident, + node->data.var.ident_len), + .size = node->data.var.ident_len, + })), + }; + break; + } + case kExprNodePlainKey: { + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ident"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(node->data.var.ident, + node->data.var.ident_len), + .size = node->data.var.ident_len, + })), + }; + break; + } + case kExprNodeEnvironment: { + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ident"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(node->data.env.ident, + node->data.env.ident_len), + .size = node->data.env.ident_len, + })), + }; + break; + } + case kExprNodeRegister: { + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("name"), + .value = INTEGER_OBJ(node->data.reg.name), + }; + break; + } + case kExprNodeComparison: { + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("cmp_type"), + .value = STRING_OBJ(cstr_to_string( + eltkn_cmp_type_tab[node->data.cmp.type])), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ccs_strategy"), + .value = STRING_OBJ(cstr_to_string( + eltkn_cmp_type_tab[node->data.cmp.ccs])), + }; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("invert"), + .value = BOOLEAN_OBJ(node->data.cmp.inv), + }; + break; + } + case kExprNodeFloat: { + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("fvalue"), + .value = FLOAT_OBJ(node->data.flt.value), + }; + break; + } + case kExprNodeInteger: { + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("ivalue"), + .value = INTEGER_OBJ((Integer)( + node->data.num.value > API_INTEGER_MAX + ? API_INTEGER_MAX + : (Integer)node->data.num.value)), + }; + break; + } + case kExprNodeMissing: + case kExprNodeOpMissing: + case kExprNodeTernary: + case kExprNodeTernaryValue: + case kExprNodeSubscript: + case kExprNodeListLiteral: + case kExprNodeUnaryPlus: + case kExprNodeBinaryPlus: + case kExprNodeNested: + case kExprNodeCall: + case kExprNodeComplexIdentifier: + case kExprNodeUnknownFigure: + case kExprNodeLambda: + case kExprNodeDictLiteral: + case kExprNodeCurlyBracesIdentifier: + case kExprNodeComma: + case kExprNodeColon: + case kExprNodeArrow: + case kExprNodeConcat: + case kExprNodeConcatOrSubscript: + case kExprNodeOr: + case kExprNodeAnd: + case kExprNodeUnaryMinus: + case kExprNodeBinaryMinus: + case kExprNodeNot: + case kExprNodeMultiplication: + case kExprNodeDivision: + case kExprNodeMod: { + break; + } + } + assert(cur_item.ret_node_p->data.dictionary.size + == cur_item.ret_node_p->data.dictionary.capacity); + xfree(*cur_item.node_p); + *cur_item.node_p = NULL; + } + } + } + kvi_destroy(ast_conv_stack); assert(ret.size == ret.capacity); + // Should be a no-op actually, leaving it in case non-nodes will need to be + // freed later. viml_pexpr_free_ast(east); viml_parser_destroy(&pstate); - return (Dictionary)ARRAY_DICT_INIT; + return ret; } -- cgit From 7bc6de75263f58c6c4f999bc86a6454ae9f28b80 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 5 Nov 2017 02:41:44 +0300 Subject: api/vim,functests: Add tests for nvim_parse_expression, fix found bugs --- src/nvim/api/vim.c | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 1aab87010e..5f725acaf7 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -995,21 +995,21 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, &pstate, parser_simple_get_line, &plines_p, colors_p); ExprAST east = viml_pexpr_parse(&pstate, pflags); - const size_t dict_size = ( + const size_t ret_size = ( 1 // "ast" - + (size_t)(east.err.arg != NULL) // "error" + + (size_t)(east.err.msg != NULL) // "error" + (size_t)highlight // "highlight" ); Dictionary ret = { - .items = xmalloc(dict_size * sizeof(ret.items[0])), + .items = xmalloc(ret_size * sizeof(ret.items[0])), .size = 0, - .capacity = dict_size, + .capacity = ret_size, }; ret.items[ret.size++] = (KeyValuePair) { .key = STATIC_CSTR_TO_STRING("ast"), .value = NIL, }; - if (east.err.arg != NULL) { + if (east.err.msg != NULL) { Dictionary err_dict = { .items = xmalloc(2 * sizeof(err_dict.items[0])), .size = 2, @@ -1017,15 +1017,22 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, }; err_dict.items[0] = (KeyValuePair) { .key = STATIC_CSTR_TO_STRING("message"), - .value = STRING_OBJ(cstr_to_string(east.err.arg)), - }; - err_dict.items[1] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("arg"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(east.err.arg, (size_t)east.err.arg_len), - .size = (size_t)east.err.arg_len, - })), + .value = STRING_OBJ(cstr_to_string(east.err.msg)), }; + if (east.err.arg == NULL) { + err_dict.items[1] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("arg"), + .value = STRING_OBJ(STRING_INIT), + }; + } else { + err_dict.items[1] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("arg"), + .value = STRING_OBJ(((String) { + .data = xmemdupz(east.err.arg, (size_t)east.err.arg_len), + .size = (size_t)east.err.arg_len, + })), + }; + } ret.items[ret.size++] = (KeyValuePair) { .key = STATIC_CSTR_TO_STRING("error"), .value = DICTIONARY_OBJ(err_dict), @@ -1055,6 +1062,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, .value = ARRAY_OBJ(hl), }; } + kvi_destroy(colors); // Walk over the AST, freeing nodes in process. ExprASTConvStack ast_conv_stack; @@ -1065,11 +1073,11 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, })); while (kv_size(ast_conv_stack)) { ExprASTConvStackItem cur_item = kv_last(ast_conv_stack); - if (*cur_item.node_p == NULL) { + ExprASTNode *const node = *cur_item.node_p; + if (node == NULL) { assert(kv_size(ast_conv_stack) == 1); kv_drop(ast_conv_stack, 1); } else { - ExprASTNode *const node = *cur_item.node_p; if (cur_item.ret_node_p->type == kObjectTypeNil) { const size_t ret_node_items_size = (size_t)( 3 // "type", "start" and "len" @@ -1116,7 +1124,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, })); } else if (node->next != NULL) { kvi_push(ast_conv_stack, ((ExprASTConvStackItem) { - .node_p = &node->children, + .node_p = &node->next, .ret_node_p = cur_item.ret_node_p + 1, })); } else if (node != NULL) { @@ -1145,7 +1153,10 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, case kExprNodeSingleQuotedString: { ret_node->items[ret_node->size++] = (KeyValuePair) { .key = STATIC_CSTR_TO_STRING("svalue"), - .value = STRING_OBJ(cstr_as_string(node->data.str.value)), + .value = STRING_OBJ(((String) { + .data = node->data.str.value, + .size = node->data.str.size, + })), }; break; } @@ -1217,7 +1228,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, ret_node->items[ret_node->size++] = (KeyValuePair) { .key = STATIC_CSTR_TO_STRING("ccs_strategy"), .value = STRING_OBJ(cstr_to_string( - eltkn_cmp_type_tab[node->data.cmp.ccs])), + ccs_tab[node->data.cmp.ccs])), }; ret_node->items[ret_node->size++] = (KeyValuePair) { .key = STATIC_CSTR_TO_STRING("invert"), -- cgit From 7849070f998902bb6aae5d6f9147d4daf5421b36 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 5 Nov 2017 21:06:12 +0300 Subject: tests: Add missing test cases --- src/nvim/api/vim.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 5f725acaf7..b12c595cb5 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -971,6 +971,11 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, switch (flags.data[i]) { case 'm': { pflags |= kExprFlagsMulti; break; } case 'E': { pflags |= kExprFlagsDisallowEOC; break; } + case NUL: { + api_set_error(err, kErrorTypeValidation, "Invalid flag: '\\0' (%u)", + (unsigned)flags.data[i]); + return (Dictionary)ARRAY_DICT_INIT; + } default: { api_set_error(err, kErrorTypeValidation, "Invalid flag: '%c' (%u)", flags.data[i], (unsigned)flags.data[i]); @@ -995,6 +1000,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, &pstate, parser_simple_get_line, &plines_p, colors_p); ExprAST east = viml_pexpr_parse(&pstate, pflags); + // FIXME add parse_length key const size_t ret_size = ( 1 // "ast" + (size_t)(east.err.msg != NULL) // "error" -- cgit From ebb59778371784ba28d37fc615ae02a5338f365d Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 6 Nov 2017 01:15:18 +0300 Subject: api/vim: Add “len” dictionary key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows determining where parsing ended which may be needed for e.g. parsing `:echo` with that API function. --- src/nvim/api/vim.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index b12c595cb5..8de37e2cf3 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -922,6 +922,12 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; /// Must contain exactly one "%.*s". /// "arg": String, error message argument. /// +/// "len": Amount of bytes successfully parsed. With flags equal to "" +/// that should be equal to the length of expr string. +/// +/// @note: “Sucessfully parsed” here means “participated in AST +/// creation”, not “till the first error”. +/// /// "ast": actual AST, either nil or a dictionary with the following /// keys: /// @@ -1000,9 +1006,8 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, &pstate, parser_simple_get_line, &plines_p, colors_p); ExprAST east = viml_pexpr_parse(&pstate, pflags); - // FIXME add parse_length key const size_t ret_size = ( - 1 // "ast" + 2 // "ast", "len" + (size_t)(east.err.msg != NULL) // "error" + (size_t)highlight // "highlight" ); @@ -1015,6 +1020,12 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, .key = STATIC_CSTR_TO_STRING("ast"), .value = NIL, }; + ret.items[ret.size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("len"), + .value = INTEGER_OBJ((Integer)(pstate.pos.line == 1 + ? plines[0].size + : pstate.pos.col)), + }; if (east.err.msg != NULL) { Dictionary err_dict = { .items = xmalloc(2 * sizeof(err_dict.items[0])), -- cgit From 842a54a1bbdd3724ba9283269b3f9899b3844e35 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 19 Aug 2017 14:13:14 +0200 Subject: doc --- src/nvim/api/vim.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 98f4410347..86f4a9d008 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -166,7 +166,10 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi) /// On VimL error: Does not fail, but updates v:errmsg. /// /// Unlike `nvim_feedkeys`, this uses a lower-level input buffer and the call -/// is not deferred. This is the most reliable way to emulate real user input. +/// is not deferred. This is the most reliable way to send real user input. +/// +/// @note |keycodes| like are translated, so `<` is special. +/// To input a literal `<`, send ``. /// /// @param keys to be typed /// @return Number of bytes actually written (can be fewer than -- cgit From 73fabf4f150e1f4e2da523b6c60b8b90797df4d2 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 23 Oct 2017 23:10:35 +0200 Subject: doc: nvim_buf_add_highlight(): zero-indexed lines --- src/nvim/api/buffer.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index c381e92dc7..f592f44f0e 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -739,29 +739,29 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err) /// Adds a highlight to buffer. /// -/// This can be used for plugins which dynamically generate highlights to a -/// buffer (like a semantic highlighter or linter). The function adds a single +/// Useful for plugins that dynamically generate highlights to a buffer +/// (like a semantic highlighter or linter). The function adds a single /// highlight to a buffer. Unlike matchaddpos() highlights follow changes to /// line numbering (as lines are inserted/removed above the highlighted line), /// like signs and marks do. /// -/// "src_id" is useful for batch deletion/updating of a set of highlights. When -/// called with src_id = 0, an unique source id is generated and returned. -/// Succesive calls can pass in it as "src_id" to add new highlights to the same -/// source group. All highlights in the same group can then be cleared with -/// nvim_buf_clear_highlight. If the highlight never will be manually deleted -/// pass in -1 for "src_id". +/// `src_id` is useful for batch deletion/updating of a set of highlights. When +/// called with `src_id = 0`, an unique source id is generated and returned. +/// Successive calls can pass that `src_id` to associate new highlights with +/// the same source group. All highlights in the same group can be cleared +/// with `nvim_buf_clear_highlight`. If the highlight never will be manually +/// deleted, pass `src_id = -1`. /// -/// If "hl_group" is the empty string no highlight is added, but a new src_id +/// If `hl_group` is the empty string no highlight is added, but a new `src_id` /// is still returned. This is useful for an external plugin to synchrounously -/// request an unique src_id at initialization, and later asynchronously add and -/// clear highlights in response to buffer changes. +/// request an unique `src_id` at initialization, and later asynchronously add +/// and clear highlights in response to buffer changes. /// /// @param buffer Buffer handle /// @param src_id Source group to use or 0 to use a new group, /// or -1 for ungrouped highlight /// @param hl_group Name of the highlight group to use -/// @param line Line to highlight +/// @param line Line to highlight (zero-indexed) /// @param col_start Start of range of columns to highlight /// @param col_end End of range of columns to highlight, /// or -1 to highlight to end of line -- cgit From 280943d9b938e95fcf77ef5290576630b84511fb Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 6 Nov 2017 02:00:39 +0100 Subject: doc: API (generated) --- src/nvim/api/buffer.c | 13 +++++++------ src/nvim/api/vim.c | 29 ++++++++++++++--------------- 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index f592f44f0e..4b6a88e5fa 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -439,6 +439,7 @@ Object nvim_buf_get_var(Buffer buffer, String name, Error *err) /// Gets a changed tick of a buffer /// /// @param[in] buffer Buffer handle. +/// @param[out] err Error details, if any /// /// @return `b:changedtick` value. Integer nvim_buf_get_changedtick(Buffer buffer, Error *err) @@ -453,14 +454,14 @@ Integer nvim_buf_get_changedtick(Buffer buffer, Error *err) return buf->b_changedtick; } -/// Get a list of dictionaries describing buffer-local mappings -/// Note that the buffer key in the dictionary will represent the buffer -/// handle where the mapping is present +/// Gets a list of dictionaries describing buffer-local mappings. +/// The "buffer" key in the returned dictionary reflects the buffer +/// handle where the mapping is present. /// -/// @param mode The abbreviation for the mode -/// @param buffer_id Buffer handle +/// @param mode Mode short-name ("n", "i", "v", ...) +/// @param buffer Buffer handle /// @param[out] err Error details, if any -/// @returns An array of maparg() like dictionaries describing mappings +/// @returns Array of maparg()-like dictionaries describing mappings ArrayOf(Dictionary) nvim_buf_get_keymap(Buffer buffer, String mode, Error *err) FUNC_API_SINCE(3) { diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 86f4a9d008..e5ec018795 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -168,8 +168,8 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi) /// Unlike `nvim_feedkeys`, this uses a lower-level input buffer and the call /// is not deferred. This is the most reliable way to send real user input. /// -/// @note |keycodes| like are translated, so `<` is special. -/// To input a literal `<`, send ``. +/// @note |keycodes| like are translated, so "<" is special. +/// To input a literal "<", send . /// /// @param keys to be typed /// @return Number of bytes actually written (can be fewer than @@ -323,15 +323,15 @@ Object nvim_execute_lua(String code, Array args, Error *err) /// @param text Some text /// @param[out] err Error details, if any /// @return Number of cells -Integer nvim_strwidth(String str, Error *err) +Integer nvim_strwidth(String text, Error *err) FUNC_API_SINCE(1) { - if (str.size > INT_MAX) { + if (text.size > INT_MAX) { api_set_error(err, kErrorTypeValidation, "String length is too high"); return 0; } - return (Integer) mb_string2cells((char_u *) str.data); + return (Integer)mb_string2cells((char_u *)text.data); } /// Gets the paths contained in 'runtimepath'. @@ -581,7 +581,7 @@ Buffer nvim_get_current_buf(void) /// Sets the current buffer /// -/// @param id Buffer handle +/// @param buffer Buffer handle /// @param[out] err Error details, if any void nvim_set_current_buf(Buffer buffer, Error *err) FUNC_API_SINCE(1) @@ -635,7 +635,7 @@ Window nvim_get_current_win(void) /// Sets the current window /// -/// @param handle Window handle +/// @param window Window handle void nvim_set_current_win(Window window, Error *err) FUNC_API_SINCE(1) { @@ -688,7 +688,7 @@ Tabpage nvim_get_current_tabpage(void) /// Sets the current tabpage /// -/// @param handle Tabpage handle +/// @param tabpage Tabpage handle /// @param[out] err Error details, if any void nvim_set_current_tabpage(Tabpage tabpage, Error *err) FUNC_API_SINCE(1) @@ -758,9 +758,8 @@ Dictionary nvim_get_color_map(void) } -/// Gets the current mode. -/// mode: Mode string. |mode()| -/// blocking: true if Nvim is waiting for input. +/// Gets the current mode. |mode()| +/// "blocking" is true if Nvim is waiting for input. /// /// @returns Dictionary { "mode": String, "blocking": Boolean } Dictionary nvim_get_mode(void) @@ -776,11 +775,11 @@ Dictionary nvim_get_mode(void) return rv; } -/// Get a list of dictionaries describing global (i.e. non-buffer) mappings -/// Note that the "buffer" key will be 0 to represent false. +/// Gets a list of dictionaries describing global (non-buffer) mappings. +/// The "buffer" key in the returned dictionary is always zero. /// -/// @param mode The abbreviation for the mode -/// @returns An array of maparg() like dictionaries describing mappings +/// @param mode Mode short-name ("n", "i", "v", ...) +/// @returns Array of maparg()-like dictionaries describing mappings ArrayOf(Dictionary) nvim_get_keymap(String mode) FUNC_API_SINCE(3) { -- cgit From 4aebd00a9eeeb2f56ff53dd4e383825e997ee7be Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 6 Nov 2017 20:28:37 +0300 Subject: *: Fix linter errors --- src/nvim/api/vim.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 0596c3ebd8..bac19ef363 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -930,7 +930,7 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; /// @note: “Sucessfully parsed” here means “participated in AST /// creation”, not “till the first error”. /// -/// "ast": actual AST, either nil or a dictionary with the following +/// "ast": actual AST, either nil or a dictionary with the following /// keys: /// /// "type": node type, one of the value names from ExprASTNodeType @@ -1009,10 +1009,10 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, ExprAST east = viml_pexpr_parse(&pstate, pflags); const size_t ret_size = ( - 2 // "ast", "len" - + (size_t)(east.err.msg != NULL) // "error" - + (size_t)highlight // "highlight" - ); + 2 // "ast", "len" + + (size_t)(east.err.msg != NULL) // "error" + + (size_t)highlight // "highlight" + + 0); Dictionary ret = { .items = xmalloc(ret_size * sizeof(ret.items[0])), .size = 0, @@ -1242,12 +1242,12 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, ret_node->items[ret_node->size++] = (KeyValuePair) { .key = STATIC_CSTR_TO_STRING("cmp_type"), .value = STRING_OBJ(cstr_to_string( - eltkn_cmp_type_tab[node->data.cmp.type])), + eltkn_cmp_type_tab[node->data.cmp.type])), }; ret_node->items[ret_node->size++] = (KeyValuePair) { .key = STATIC_CSTR_TO_STRING("ccs_strategy"), .value = STRING_OBJ(cstr_to_string( - ccs_tab[node->data.cmp.ccs])), + ccs_tab[node->data.cmp.ccs])), }; ret_node->items[ret_node->size++] = (KeyValuePair) { .key = STATIC_CSTR_TO_STRING("invert"), @@ -1266,9 +1266,9 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, ret_node->items[ret_node->size++] = (KeyValuePair) { .key = STATIC_CSTR_TO_STRING("ivalue"), .value = INTEGER_OBJ((Integer)( - node->data.num.value > API_INTEGER_MAX - ? API_INTEGER_MAX - : (Integer)node->data.num.value)), + node->data.num.value > API_INTEGER_MAX + ? API_INTEGER_MAX + : (Integer)node->data.num.value)), }; break; } -- cgit From c7495ebcc0918ffd682083408895451318e41d1f Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 12 Nov 2017 02:18:43 +0300 Subject: viml/parser/expressions: Add support for parsing assignments --- src/nvim/api/vim.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index bac19ef363..ce554d351c 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -900,14 +900,21 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; /// Parse a VimL expression /// /// @param[in] expr Expression to parse. Is always treated as a single line. -/// @param[in] flags Flags: "m" if multiple expressions in a row are allowed -/// (only the first one will be parsed), "E" if EOC tokens -/// are not allowed (determines whether they will stop -/// parsing process or be recognized as an operator/space, -/// though also yielding an error). -/// -/// Use only "m" to parse like for "=", only "E" to -/// parse like for ":echo", empty string for ":let". +/// @param[in] flags Flags: +/// +/// - "m" if multiple expressions in a row are allowed (only +/// the first one will be parsed), +/// - "E" if EOC tokens are not allowed (determines whether +/// they will stop parsing process or be recognized as an +/// operator/space, though also yielding an error). +/// - "l" when needing to start parsing with lvalues for +/// ":let" or ":for". +/// +/// Common flag sets: +/// - "m" to parse like for ":echo". +/// - "E" to parse like for "=". +/// - empty string for ":call". +/// - "lm" to parse for ":let". /// @param[in] highlight If true, return value will also include "highlight" /// key containing array of 4-tuples (arrays) (Integer, /// Integer, Integer, String), where first three numbers @@ -964,6 +971,9 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; /// value names from ExprCaseCompareStrategy, /// stringified without "kCCStrategy" prefix. Only /// present for "Comparison" nodes. +/// "augmentation": String, augmentation type for "Assignment" nodes. +/// Is either an empty string, "Add", "Subtract" or +/// "Concat" for "=", "+=", "-=" or ".=" respectively. /// "invert": Boolean, true if result of comparison needs to be /// inverted. Only present for "Comparison" nodes. /// "ivalue": Integer, integer value for "Integer" nodes. @@ -979,6 +989,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, switch (flags.data[i]) { case 'm': { pflags |= kExprFlagsMulti; break; } case 'E': { pflags |= kExprFlagsDisallowEOC; break; } + case 'l': { pflags |= kExprFlagsParseLet; break; } case NUL: { api_set_error(err, kErrorTypeValidation, "Invalid flag: '\\0' (%u)", (unsigned)flags.data[i]); @@ -1114,6 +1125,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, + (node->type == kExprNodeFloat) // "fvalue" + (node->type == kExprNodeDoubleQuotedString || node->type == kExprNodeSingleQuotedString) // "svalue" + + (node->type == kExprNodeAssignment) // "augmentation" + 0); Dictionary ret_node = { .items = xmalloc(ret_node_items_size * sizeof(ret_node.items[0])), @@ -1272,6 +1284,17 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, }; break; } + case kExprNodeAssignment: { + const ExprAssignmentType asgn_type = node->data.ass.type; + ret_node->items[ret_node->size++] = (KeyValuePair) { + .key = STATIC_CSTR_TO_STRING("augmentation"), + .value = STRING_OBJ( + asgn_type == kExprAsgnPlain + ? (String)STRING_INIT + : cstr_to_string(expr_asgn_type_tab[asgn_type])), + }; + break; + } case kExprNodeMissing: case kExprNodeOpMissing: case kExprNodeTernary: -- cgit From 0407ddb36464c46086b608baebf7eed8a9ab60d5 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sat, 11 Nov 2017 10:48:04 -0500 Subject: Use PRId64 to format Integer when calling api_set_error Integer is a 64-bit type so using %d can produce incorrect results. test/functional/api/highlight_spec.lua @ 35: highlight api nvim_get_hl_by_id ...W7Xi/neovim-0.2.1/test/functional/api/highlight_spec.lua:46: Expected objects to be the same. Passed in: (string) 'Invalid highlight id: 7671724' Expected: (string) 'Invalid highlight id: 30000' --- src/nvim/api/vim.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index e5ec018795..d2b0e329c9 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -89,7 +89,8 @@ Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Error *err) { Dictionary dic = ARRAY_DICT_INIT; if (syn_get_final_id((int)hl_id) == 0) { - api_set_error(err, kErrorTypeException, "Invalid highlight id: %d", hl_id); + api_set_error(err, kErrorTypeException, + "Invalid highlight id: %" PRId64, hl_id); return dic; } int attrcode = syn_id2attr((int)hl_id); -- cgit From c030a381684f3491decf5597b16dfa9a21f29500 Mon Sep 17 00:00:00 2001 From: Peter Kalauskas Date: Mon, 20 Nov 2017 11:27:06 -0800 Subject: helpers.c: statically assert integer falls within range --- src/nvim/api/private/helpers.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 2944925a9c..6808048ac8 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -12,6 +12,7 @@ #include "nvim/api/private/handle.h" #include "nvim/msgpack_rpc/helpers.h" #include "nvim/ascii.h" +#include "nvim/assert.h" #include "nvim/vim.h" #include "nvim/buffer.h" #include "nvim/window.h" @@ -760,12 +761,9 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err) case kObjectTypeWindow: case kObjectTypeTabpage: case kObjectTypeInteger: - if (obj.data.integer > VARNUMBER_MAX - || obj.data.integer < VARNUMBER_MIN) { - api_set_error(err, kErrorTypeValidation, "Integer value outside range"); - return false; - } - + STATIC_ASSERT(sizeof(obj.data.integer) <= sizeof(varnumber_T), + "Expected integer size to be less than or equal to VimL " + "number size"); tv->v_type = VAR_NUMBER; tv->vval.v_number = (varnumber_T)obj.data.integer; break; -- cgit From 5215e3205a07b85e4e4cf1f8a8ca6be2b9556459 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 27 Aug 2017 11:59:33 +0200 Subject: channels: refactor --- src/nvim/api/ui.c | 2 +- src/nvim/api/vim.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index afbee09c1c..a9eaccfac5 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -252,7 +252,7 @@ static void remote_ui_flush(UI *ui) { UIData *data = ui->data; if (data->buffer.size > 0) { - channel_send_event(data->channel_id, "redraw", data->buffer); + rpc_send_event(data->channel_id, "redraw", data->buffer); data->buffer = (Array)ARRAY_DICT_INIT; } } diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index d2b0e329c9..f4ccf07bec 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -721,7 +721,7 @@ void nvim_subscribe(uint64_t channel_id, String event) char e[METHOD_MAXLEN + 1]; memcpy(e, event.data, length); e[length] = NUL; - channel_subscribe(channel_id, e); + rpc_subscribe(channel_id, e); } /// Unsubscribes to event broadcasts @@ -737,7 +737,7 @@ void nvim_unsubscribe(uint64_t channel_id, String event) char e[METHOD_MAXLEN + 1]; memcpy(e, event.data, length); e[length] = NUL; - channel_unsubscribe(channel_id, e); + rpc_unsubscribe(channel_id, e); } Integer nvim_get_color_by_name(String name) -- cgit From 17077b68133a62d0dc1b84cb48779464c117e028 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 26 Nov 2017 16:08:53 +0300 Subject: viml/parser/expressions: Make $ENV not depend on &isident --- src/nvim/api/vim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 7838f9faa3..a0816dbc8e 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -983,7 +983,7 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; /// "DoubleQuotedString" nodes. Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, Error *err) - FUNC_API_SINCE(4) + FUNC_API_SINCE(4) FUNC_API_ASYNC { int pflags = 0; for (size_t i = 0 ; i < flags.size ; i++) { -- cgit From 274f32d42e61e6f6c76b9ca499f5b79f256a481a Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 10 Dec 2017 03:39:51 +0300 Subject: *: Start hiding list implementation Most of files, except for eval.c and eval/* were only processed by perl. --- src/nvim/api/private/helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 629873998e..e5a1e150f9 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -798,7 +798,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err) tv_list_append(list, li); } - list->lv_refcount++; + tv_list_ref(list); tv->v_type = VAR_LIST; tv->vval.v_list = list; -- cgit From dc232b74fb1a7927d6c13bd8c80bb42fc18a859f Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 10 Dec 2017 01:24:54 +0100 Subject: doc: hack to avoid doxygen bug Use `@cond ` to obscure a section from doxygen. doxygen thinks kvec_withinit_t() is a function. That adds noise to the generated API documentation, and also prevents the following function from being noticed. --- src/nvim/api/vim.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 416e7d22d2..f0db391abe 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -789,6 +789,10 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode) return keymap_array(mode, NULL); } +/// Returns a 2-tuple (Array), where item 0 is the current channel id and item +/// 1 is the |api-metadata| map (Dictionary). +/// +/// @returns 2-tuple [{channel-id}, {api-metadata}] Array nvim_get_api_info(uint64_t channel_id) FUNC_API_SINCE(1) FUNC_API_ASYNC FUNC_API_REMOTE_ONLY { @@ -896,7 +900,9 @@ typedef struct { Object *ret_node_p; } ExprASTConvStackItem; +///@cond DOXYGEN_NOT_A_FUNCTION typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; +///@endcond /// Parse a VimL expression /// -- cgit From ad9c2d3cb97bbc4ba83ce7d23c9df23f9d3d11db Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 14 Nov 2017 10:47:49 +0100 Subject: doc closes #7622 --- src/nvim/api/buffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 4b6a88e5fa..fdde28f2bb 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -763,8 +763,8 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err) /// or -1 for ungrouped highlight /// @param hl_group Name of the highlight group to use /// @param line Line to highlight (zero-indexed) -/// @param col_start Start of range of columns to highlight -/// @param col_end End of range of columns to highlight, +/// @param col_start Start of (byte-indexed) column range to highlight +/// @param col_end End of (byte-indexed) column range to highlight, /// or -1 to highlight to end of line /// @param[out] err Error details, if any /// @return The src_id that was used -- cgit From ac4bbf55f6d6b9b252dd90fe800626850022b690 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 10 Dec 2017 22:04:43 +0300 Subject: *: Hide list implementation in other files as well --- src/nvim/api/private/helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index e5a1e150f9..4492f8bb93 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -789,7 +789,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err) Object item = obj.data.array.items[i]; listitem_T *li = tv_list_item_alloc(); - if (!object_to_vim(item, &li->li_tv, err)) { + if (!object_to_vim(item, TV_LIST_ITEM_TV(li), err)) { // cleanup tv_list_item_free(li); tv_list_free(list); -- cgit From 45998deb5d325c7a44ce38b0c7d954919458f105 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 12 Dec 2017 00:52:14 +0300 Subject: *: Fix linter errors --- src/nvim/api/vim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index f0db391abe..c0daac8085 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -900,9 +900,9 @@ typedef struct { Object *ret_node_p; } ExprASTConvStackItem; -///@cond DOXYGEN_NOT_A_FUNCTION +/// @cond DOXYGEN_NOT_A_FUNCTION typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; -///@endcond +/// @endcond /// Parse a VimL expression /// -- cgit From 34057045beca40406673ff421a4ef1e8e8c08853 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Tue, 12 Dec 2017 18:23:19 +0100 Subject: ui: forward relevant option updates to UIs (#7520) also make termguicolors mutable after startup --- src/nvim/api/ui.c | 1 + src/nvim/api/ui_events.in.h | 2 ++ 2 files changed, 3 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index a9eaccfac5..35508fde6b 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -93,6 +93,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, ui->suspend = remote_ui_suspend; ui->set_title = remote_ui_set_title; ui->set_icon = remote_ui_set_icon; + ui->option_set = remote_ui_option_set; ui->event = remote_ui_event; memset(ui->ui_ext, 0, sizeof(ui->ui_ext)); diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index 847b21072a..3d2253e918 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -58,6 +58,8 @@ void set_title(String title) FUNC_API_SINCE(3); void set_icon(String icon) FUNC_API_SINCE(3); +void option_set(String name, Object value) + FUNC_API_SINCE(4) FUNC_API_BRIDGE_IMPL; void popupmenu_show(Array items, Integer selected, Integer row, Integer col) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; -- cgit From 0c533a488fbe453ae39017a586eff7813da8ed8a Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 24 Dec 2017 01:43:42 +0300 Subject: *: Remove most calls to tv_list_item_alloc Still left calls in eval/typval.c and test/unit/eval/helpers.lua. Latter is the only reason why function did not receive `static` modifier. --- src/nvim/api/private/helpers.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 4492f8bb93..26ad7ac1a6 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -787,16 +787,14 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err) for (uint32_t i = 0; i < obj.data.array.size; i++) { Object item = obj.data.array.items[i]; - listitem_T *li = tv_list_item_alloc(); + typval_T li_tv; - if (!object_to_vim(item, TV_LIST_ITEM_TV(li), err)) { - // cleanup - tv_list_item_free(li); + if (!object_to_vim(item, &li_tv, err)) { tv_list_free(list); return false; } - tv_list_append(list, li); + tv_list_append_owned_tv(list, li_tv); } tv_list_ref(list); -- cgit From fe60fa9faafd90cfe756c80119abae6f8906fc4b Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 16 Dec 2017 21:33:59 +0100 Subject: doc vim-patch:8.0.1206: no autocmd for entering or leaving the command line (commit a4f6cec7a31ff8dbfa089b9e22227afbeb951e9b) NA patches: vim-patch:8.0.0320: warning for unused variable with small build --- src/nvim/api/vim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index c0daac8085..172f2ce18e 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -929,7 +929,7 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; /// starting column and ending column (latter exclusive: /// one should highlight region [start_col, end_col)). /// -/// @return AST: top-level dictionary holds keys +/// @return AST: top-level dictionary with these keys: /// /// "error": Dictionary with error, present only if parser saw some /// error. Contains the following keys: -- cgit From c095f83116eb8ef87983ca5fea61053755fbc4e5 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 5 Jan 2018 11:17:21 +0100 Subject: api: change nvim_command_output behavior Implement nvim_command_output with `execute({cmd},"silent")`. Behavior changes: - does not provoke any hit-enter prompt - no longer prepends a newline char - does not capture some noise (like the "[New File]" message, see the change to tabnewentered_spec.lua) Technically ("bug-for-bug") this a breaking change. But the previous behavior of nvim_command_output meant that it probably wasn't used for anything outside of tests. Also remove the undocumented `v:command_output` variable which was a hack introduced only for the purposes of nvim_command_output. closes #7726 --- src/nvim/api/vim.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 172f2ce18e..8929bc5b9b 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -43,14 +43,15 @@ #endif /// Executes an ex-command. -/// On VimL error: Returns the VimL error; v:errmsg is not updated. +/// +/// On parse error: forwards the Vim error; does not update v:errmsg. +/// On runtime error: forwards the Vim error; does not update v:errmsg. /// /// @param command Ex-command string -/// @param[out] err Error details (including actual VimL error), if any +/// @param[out] err Error details (Vim error), if any void nvim_command(String command, Error *err) FUNC_API_SINCE(1) { - // Run the command try_start(); do_cmdline_cmd(command.data); update_screen(VALID); @@ -207,18 +208,39 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, return cstr_as_string(ptr); } -String nvim_command_output(String str, Error *err) +/// Executes an ex-command and returns its (non-error) output. +/// Shell |:!| output is not captured. +/// +/// On parse error: forwards the Vim error; does not update v:errmsg. +/// On runtime error: forwards the Vim error; does not update v:errmsg. +/// +/// @param command Ex-command string +/// @param[out] err Error details (Vim error), if any +String nvim_command_output(String command, Error *err) FUNC_API_SINCE(1) { - do_cmdline_cmd("redir => v:command_output"); - nvim_command(str, err); - do_cmdline_cmd("redir END"); - + Array args = ARRAY_DICT_INIT; + ADD(args, STRING_OBJ(copy_string(command))); + ADD(args, STRING_OBJ(cstr_to_string("silent"))); + String fn = cstr_to_string("execute"); + Object rv = nvim_call_function(fn, args, err); + api_free_string(fn); + api_free_array(args); if (ERROR_SET(err)) { + assert(rv.type == kObjectTypeNil); return (String)STRING_INIT; } - return cstr_to_string((char *)get_vim_var_str(VV_COMMAND_OUTPUT)); + assert(rv.type == kObjectTypeString); + // execute() always(?) prepends a newline; remove it. + if (rv.data.string.size > 1) { + assert(rv.data.string.data[0] == '\n'); + String *s = &rv.data.string; + s->size--; + memmove(s->data, s->data + 1, s->size); + s->data[s->size] = '\0'; + } + return rv.data.string; } /// Evaluates a VimL expression (:help expression). -- cgit From 5055d4a755d3c100cddf51bded77abca04beb971 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 9 Jan 2018 10:36:25 +0100 Subject: api: nvim_command_output: direct impl --- src/nvim/api/vim.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 8929bc5b9b..0e7cc428d4 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -219,28 +219,38 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, String nvim_command_output(String command, Error *err) FUNC_API_SINCE(1) { - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(copy_string(command))); - ADD(args, STRING_OBJ(cstr_to_string("silent"))); - String fn = cstr_to_string("execute"); - Object rv = nvim_call_function(fn, args, err); - api_free_string(fn); - api_free_array(args); + const int save_msg_silent = msg_silent; + garray_T *const save_capture_ga = capture_ga; + garray_T capture_local; + ga_init(&capture_local, 1, 80); + + try_start(); + msg_silent++; + capture_ga = &capture_local; + do_cmdline_cmd(command.data); + capture_ga = save_capture_ga; + msg_silent = save_msg_silent; + try_end(err); + if (ERROR_SET(err)) { - assert(rv.type == kObjectTypeNil); - return (String)STRING_INIT; + goto theend; } - assert(rv.type == kObjectTypeString); - // execute() always(?) prepends a newline; remove it. - if (rv.data.string.size > 1) { - assert(rv.data.string.data[0] == '\n'); - String *s = &rv.data.string; - s->size--; - memmove(s->data, s->data + 1, s->size); - s->data[s->size] = '\0'; + if (capture_local.ga_len > 1) { + // redir always(?) prepends a newline; remove it. + char *s = capture_local.ga_data; + assert(s[0] == '\n'); + memmove(s, s + 1, (size_t)capture_local.ga_len); + s[capture_local.ga_len - 1] = '\0'; + return (String) { // Caller will free the memory. + .data = s, + .size = (size_t)(capture_local.ga_len - 1), + }; } - return rv.data.string; + +theend: + ga_clear(&capture_local); + return (String)STRING_INIT; } /// Evaluates a VimL expression (:help expression). -- cgit From 9ea1752d60589e8fc5e7184144bc6d1c1b9f16a3 Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 3 Jan 2018 00:00:16 +0300 Subject: *: Provide list length when allocating lists --- src/nvim/api/private/helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 26ad7ac1a6..9baa996560 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -783,7 +783,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err) break; case kObjectTypeArray: { - list_T *const list = tv_list_alloc(); + list_T *const list = tv_list_alloc((ptrdiff_t)obj.data.array.size); for (uint32_t i = 0; i < obj.data.array.size; i++) { Object item = obj.data.array.items[i]; -- cgit From ac87d9de697204685143ea6d4c99675e18e96609 Mon Sep 17 00:00:00 2001 From: mkotha Date: Tue, 16 Jan 2018 05:45:10 +0900 Subject: Fix an off-by-one error in the documentation of nvim_buf_clear_highlight (#7853) --- src/nvim/api/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index fdde28f2bb..01dde9dd09 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -806,7 +806,7 @@ Integer nvim_buf_add_highlight(Buffer buffer, /// Clears highlights from a given source group and a range of lines /// -/// To clear a source group in the entire buffer, pass in 1 and -1 to +/// To clear a source group in the entire buffer, pass in 0 and -1 to /// line_start and line_end respectively. /// /// @param buffer Buffer handle -- cgit From 06994e0e21eb5545aef7c2234f5d1a271865366e Mon Sep 17 00:00:00 2001 From: George Zhao Date: Wed, 17 Jan 2018 19:35:57 +0800 Subject: Fix warning about conversion on mingw64 --- src/nvim/api/buffer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 01dde9dd09..af723639c5 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -399,7 +399,11 @@ void nvim_buf_set_lines(uint64_t channel_id, // Only adjust marks if we managed to switch to a window that holds // the buffer, otherwise line numbers will be invalid. if (save_curbuf.br_buf == NULL) { - mark_adjust((linenr_T)start, (linenr_T)(end - 1), MAXLNUM, extra, false); + mark_adjust((linenr_T)start, + (linenr_T)(end - 1), + MAXLNUM, + (long)extra, + false); } changed_lines((linenr_T)start, 0, (linenr_T)end, (long)extra); -- cgit From c6fe06bbc09c0adbb3ef30be9f5b238e802b5038 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 27 Jan 2018 13:52:45 +0100 Subject: tui: fix use-after-free after UI `stop` event #7922 ui_bridge:ui_bridge_stop() calls ui_detach_impl() last, so the check for ui_active() in ui:ui_refresh() doesn't help: tui_main() already freed the `ui` object. There is a race between ui_bridge_stop (thread T0) and tui_main (thread T1). UIBridgeData.stopped could be set while ui_bridge_stop() is in the middle of loop_poll_events(), which may invoke tui_scheduler() on T0. The pointers in tui_scheduler() may be invalid by then. Solution(?): Use the `UI.data` field as a "stopped" flag and check it in tui_scheduler(). ASAN use-after-free report observed in #7908: = ==20066==ERROR: AddressSanitizer: heap-use-after-free on address 0x611000000cd0 at pc 0x00000182abed bp 0x7ffe23b07070 sp 0x7ffe23b07068 = READ of size 8 at 0x611000000cd0 thread T0 = 0 0x182abec in tui_scheduler /home/travis/build/neovim/neovim/src/nvim/tui/tui.c:393:23 = 1 0x1876afd in ui_bridge_update_fg /home/travis/build/neovim/neovim/build/src/nvim/auto/ui_events_bridge.generated.h:205:3 = 2 0x186c130 in ui_resize /home/travis/build/neovim/neovim/src/nvim/ui.c:310:3 = 3 0x146b9c2 in screen_resize /home/travis/build/neovim/neovim/src/nvim/screen.c:7483:3 = 4 0x186a6f0 in ui_refresh /home/travis/build/neovim/neovim/src/nvim/ui.c:284:3 = 5 0x186bbe0 in ui_refresh_event /home/travis/build/neovim/neovim/src/nvim/ui.c:297:3 = 6 0xa2219a in multiqueue_process_events /home/travis/build/neovim/neovim/src/nvim/event/multiqueue.c:150:7 = 7 0xa1bd7f in loop_poll_events /home/travis/build/neovim/neovim/src/nvim/event/loop.c:63:3 = 8 0x1872709 in ui_bridge_stop /home/travis/build/neovim/neovim/src/nvim/ui_bridge.c:121:5 = 9 0x1864247 in ui_builtin_stop /home/travis/build/neovim/neovim/src/nvim/ui.c:143:3 = 10 0x1249ec8 in mch_exit /home/travis/build/neovim/neovim/src/nvim/os_unix.c:140:3 = 11 0xe56ba9 in getout /home/travis/build/neovim/neovim/src/nvim/main.c:671:3 = 12 0xfc4c8f in preserve_exit /home/travis/build/neovim/neovim/src/nvim/misc1.c:2653:3 = 13 0x1247c02 in deadly_signal /home/travis/build/neovim/neovim/src/nvim/os/signal.c:137:3 = 14 0x1247921 in on_signal /home/travis/build/neovim/neovim/src/nvim/os/signal.c:162:9 = 15 0xa35618 in signal_event /home/travis/build/neovim/neovim/src/nvim/event/signal.c:47:3 = 16 0xa2219a in multiqueue_process_events /home/travis/build/neovim/neovim/src/nvim/event/multiqueue.c:150:7 = 17 0xa1bd7f in loop_poll_events /home/travis/build/neovim/neovim/src/nvim/event/loop.c:63:3 = 18 0x1237bd6 in input_poll /home/travis/build/neovim/neovim/src/nvim/os/input.c:349:3 = 19 0x123334f in inbuf_poll /home/travis/build/neovim/neovim/src/nvim/os/input.c:372:24 = 20 0x123316d in os_inchar /home/travis/build/neovim/neovim/src/nvim/os/input.c:110:19 = 21 0x170d20e in state_enter /home/travis/build/neovim/neovim/src/nvim/state.c:55:13 = 22 0xbd7441 in command_line_enter /home/travis/build/neovim/neovim/src/nvim/ex_getln.c:384:3 = 23 0xbd0a60 in getcmdline /home/travis/build/neovim/neovim/src/nvim/ex_getln.c:1920:10 = 24 0xbdb365 in getexline /home/travis/build/neovim/neovim/src/nvim/ex_getln.c:2100:10 = 25 0xb00a6b in do_cmdline /home/travis/build/neovim/neovim/src/nvim/ex_docmd.c:528:47 = 26 0x10a7837 in nv_colon /home/travis/build/neovim/neovim/src/nvim/normal.c:4552:18 = 27 0x1091e15 in normal_execute /home/travis/build/neovim/neovim/src/nvim/normal.c:1136:3 = 28 0x170d439 in state_enter /home/travis/build/neovim/neovim/src/nvim/state.c:67:26 = 29 0x104ee14 in normal_enter /home/travis/build/neovim/neovim/src/nvim/normal.c:466:3 = 30 0xe4295c in main /home/travis/build/neovim/neovim/src/nvim/main.c:572:3 = 31 0x2b2ba340bf44 in __libc_start_main /build/eglibc-ripdx6/eglibc-2.19/csu/libc-start.c:287 = 32 0x44d24b in _start (/home/travis/build/neovim/neovim/build/bin/nvim+0x44d24b) = = 0x611000000cd0 is located 16 bytes inside of 240-byte region [0x611000000cc0,0x611000000db0) = freed by thread T1 here: = 0 0x4ee0e2 in __interceptor_free /local/mnt/workspace/tmp/ubuntu_rel/llvm/utils/release/final/llvm.src/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:47:3 = 1 0xf4f6d4 in xfree /home/travis/build/neovim/neovim/src/nvim/memory.c:133:3 = 2 0x182a963 in tui_main /home/travis/build/neovim/neovim/src/nvim/tui/tui.c:383:3 = 3 0x18792b0 in ui_thread_run /home/travis/build/neovim/neovim/src/nvim/ui_bridge.c:106:3 = 4 0x2b2ba2697183 in start_thread /build/eglibc-ripdx6/eglibc-2.19/nptl/pthread_create.c:312 = = previously allocated by thread T0 here: = 0 0x4ee61a in calloc /local/mnt/workspace/tmp/ubuntu_rel/llvm/utils/release/final/llvm.src/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:76:3 = 1 0xf4f787 in xcalloc /home/travis/build/neovim/neovim/src/nvim/memory.c:147:15 = 2 0x182000a in tui_start /home/travis/build/neovim/neovim/src/nvim/tui/tui.c:127:12 = 3 0x1863f7c in ui_builtin_start /home/travis/build/neovim/neovim/src/nvim/ui.c:125:3 = 4 0xe41bb9 in main /home/travis/build/neovim/neovim/src/nvim/main.c:457:5 = 5 0x2b2ba340bf44 in __libc_start_main /build/eglibc-ripdx6/eglibc-2.19/csu/libc-start.c:287 = = Thread T1 created by T0 here: = 0 0x4d774d in __interceptor_pthread_create /local/mnt/workspace/tmp/ubuntu_rel/llvm/utils/release/final/llvm.src/projects/compiler-rt/lib/asan/asan_interceptors.cc:317:3 = 1 0x1aae6b0 in uv_thread_create /home/travis/nvim-deps/build/src/libuv/src/unix/thread.c:75 = 2 0x18217fa in tui_start /home/travis/build/neovim/neovim/src/nvim/tui/tui.c:159:10 = 3 0x1863f7c in ui_builtin_start /home/travis/build/neovim/neovim/src/nvim/ui.c:125:3 = 4 0xe41bb9 in main /home/travis/build/neovim/neovim/src/nvim/main.c:457:5 = 5 0x2b2ba340bf44 in __libc_start_main /build/eglibc-ripdx6/eglibc-2.19/csu/libc-start.c:287 --- Alternative attempt: commit 6ad9c02491606a0c31e907f38c9931f324327aa5 Author: Justin M. Keyes Date: Sat Jan 27 15:12:58 2018 +0100 tui: fix use-after-free: swap in empty scheduler This should make life easier for UIs like VimR which implement their own in-process bridged UI: they don't need to worry that their `scheduler` might receive an invalid pointer. To avoid that, ui_bridge_stopped() swaps in an empty scheduler. Note that this requires the call to loop_poll_events() to be moved into the critical section. diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c index 779585416f80..491052d19d3b 100644 --- a/src/nvim/ui_bridge.c +++ b/src/nvim/ui_bridge.c @@ -93,10 +93,18 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler) return &rv->bridge; } +static void ui_bridge_null_scheduler(Event event, void *d) +{ + WLOG("ignoring event (bridge stopped)"); +} + void ui_bridge_stopped(UIBridgeData *bridge) { uv_mutex_lock(&bridge->mutex); bridge->stopped = true; + // Replace with an empty scheduler, so that the UI internal scheduler does + // not get invoked with an invalid pointer. #7922 + bridge->scheduler = ui_bridge_null_scheduler; uv_mutex_unlock(&bridge->mutex); } @@ -111,14 +119,11 @@ static void ui_bridge_stop(UI *b) UIBridgeData *bridge = (UIBridgeData *)b; bool stopped = bridge->stopped = false; UI_BRIDGE_CALL(b, stop, 1, b); - for (;;) { + while (!stopped) { uv_mutex_lock(&bridge->mutex); stopped = bridge->stopped; - uv_mutex_unlock(&bridge->mutex); - if (stopped) { - break; - } loop_poll_events(&main_loop, 10); // Process one event (at most). + uv_mutex_unlock(&bridge->mutex); } uv_thread_join(&bridge->ui_thread); uv_mutex_destroy(&bridge->mutex); --- src/nvim/api/ui.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 35508fde6b..760c95eb5b 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -43,10 +43,10 @@ void remote_ui_disconnect(uint64_t channel_id) return; } UIData *data = ui->data; - // destroy pending screen updates - api_free_array(data->buffer); + api_free_array(data->buffer); // Destroy pending screen updates. pmap_del(uint64_t)(connected_uis, channel_id); xfree(ui->data); + ui->data = NULL; // Flag UI as "stopped". ui_detach_impl(ui); xfree(ui); } -- cgit From 5d8da126d0b5ab7f550a74264ba434a2ad04280e Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Tue, 6 Feb 2018 19:46:45 +0100 Subject: ui/tui: highlighting refactor Make HlAttr contain highlighting state for both color modes (cterm and rgb). This allows us to implement termguicolors completely in the TUI. Simplify some logic duplicated between ui.c and screen.c. Also avoid some superfluous highlighting reset events. --- src/nvim/api/ui.c | 3 ++- src/nvim/api/ui_events.in.h | 11 +++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 760c95eb5b..e53a45bd93 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -86,6 +86,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, ui->put = remote_ui_put; ui->bell = remote_ui_bell; ui->visual_bell = remote_ui_visual_bell; + ui->default_colors_set = remote_ui_default_colors_set; ui->update_fg = remote_ui_update_fg; ui->update_bg = remote_ui_update_bg; ui->update_sp = remote_ui_update_sp; @@ -243,7 +244,7 @@ static void push_call(UI *ui, char *name, Array args) static void remote_ui_highlight_set(UI *ui, HlAttrs attrs) { Array args = ARRAY_DICT_INIT; - Dictionary hl = hlattrs2dict(attrs); + Dictionary hl = hlattrs2dict(&attrs, ui->rgb); ADD(args, DICTIONARY_OBJ(hl)); push_call(ui, "highlight_set", args); diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index 3d2253e918..c599b0ce72 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -47,11 +47,14 @@ void visual_bell(void) void flush(void) FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL; void update_fg(Integer fg) - FUNC_API_SINCE(3); + FUNC_API_SINCE(3) FUNC_API_BRIDGE_IMPL; void update_bg(Integer bg) - FUNC_API_SINCE(3); + FUNC_API_SINCE(3) FUNC_API_BRIDGE_IMPL; void update_sp(Integer sp) - FUNC_API_SINCE(3); + FUNC_API_SINCE(3) FUNC_API_BRIDGE_IMPL; +void default_colors_set(Integer rgb_fg, Integer rgb_bg, Integer rgb_sp, + Integer cterm_fg, Integer cterm_bg) + FUNC_API_SINCE(4); void suspend(void) FUNC_API_SINCE(3) FUNC_API_BRIDGE_IMPL; void set_title(String title) @@ -59,7 +62,7 @@ void set_title(String title) void set_icon(String icon) FUNC_API_SINCE(3); void option_set(String name, Object value) - FUNC_API_SINCE(4) FUNC_API_BRIDGE_IMPL; + FUNC_API_SINCE(4); void popupmenu_show(Array items, Integer selected, Integer row, Integer col) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; -- cgit From 6e5cb0debd23693175bd05409d3f1af4015567df Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Tue, 13 Feb 2018 13:45:49 +0100 Subject: ui: refactor ui options --- src/nvim/api/private/helpers.c | 7 +++++++ src/nvim/api/ui.c | 30 +++++++++++++----------------- 2 files changed, 20 insertions(+), 17 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 9baa996560..65c306d4b1 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -26,6 +26,7 @@ #include "nvim/version.h" #include "nvim/lib/kvec.h" #include "nvim/getchar.h" +#include "nvim/ui.h" /// Helper structure for vim_to_object typedef struct { @@ -955,6 +956,12 @@ static void init_ui_event_metadata(Dictionary *metadata) msgpack_rpc_to_object(&unpacked.data, &ui_events); msgpack_unpacked_destroy(&unpacked); PUT(*metadata, "ui_events", ui_events); + Array ui_options = ARRAY_DICT_INIT; + ADD(ui_options, STRING_OBJ(cstr_to_string("rgb"))); + for (UIExtension i = 0; i < kUIExtCount; i++) { + ADD(ui_options, STRING_OBJ(cstr_to_string(ui_ext_names[i]))); + } + PUT(*metadata, "ui_options", ARRAY_OBJ(ui_options)); } static void init_error_type_metadata(Dictionary *metadata) diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index e53a45bd93..4870c3fb8a 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -176,18 +176,6 @@ void nvim_ui_set_option(uint64_t channel_id, String name, static void ui_set_option(UI *ui, String name, Object value, Error *error) { -#define UI_EXT_OPTION(o, e) \ - do { \ - if (strequal(name.data, #o)) { \ - if (value.type != kObjectTypeBoolean) { \ - api_set_error(error, kErrorTypeValidation, #o " must be a Boolean"); \ - return; \ - } \ - ui->ui_ext[(e)] = value.data.boolean; \ - return; \ - } \ - } while (0) - if (strequal(name.data, "rgb")) { if (value.type != kObjectTypeBoolean) { api_set_error(error, kErrorTypeValidation, "rgb must be a Boolean"); @@ -197,13 +185,21 @@ static void ui_set_option(UI *ui, String name, Object value, Error *error) return; } - UI_EXT_OPTION(ext_cmdline, kUICmdline); - UI_EXT_OPTION(ext_popupmenu, kUIPopupmenu); - UI_EXT_OPTION(ext_tabline, kUITabline); - UI_EXT_OPTION(ext_wildmenu, kUIWildmenu); + for (UIExtension i = 0; i < kUIExtCount; i++) { + if (strequal(name.data, ui_ext_names[i])) { + if (value.type != kObjectTypeBoolean) { + snprintf((char *)IObuff, IOSIZE, "%s must be a Boolean", + ui_ext_names[i]); + api_set_error(error, kErrorTypeValidation, (char *)IObuff); + return; + } + ui->ui_ext[i] = value.data.boolean; + return; + } + } if (strequal(name.data, "popupmenu_external")) { - // LEGACY: Deprecated option, use `ui_ext` instead. + // LEGACY: Deprecated option, use `ext_cmdline` instead. if (value.type != kObjectTypeBoolean) { api_set_error(error, kErrorTypeValidation, "popupmenu_external must be a Boolean"); -- cgit From 9f994bb69925ed943b17d03f2cad7d5e2c21e992 Mon Sep 17 00:00:00 2001 From: geekodour Date: Fri, 16 Feb 2018 14:10:40 +0530 Subject: api: nvim_list_uis #8004 ref #7438 closes #4842 --- src/nvim/api/vim.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 0e7cc428d4..dad67c5e4b 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -35,6 +35,7 @@ #include "nvim/os/input.h" #include "nvim/viml/parser/expressions.h" #include "nvim/viml/parser/parser.h" +#include "nvim/ui.h" #define LINE_BUFFER_SIZE 4096 @@ -1468,3 +1469,12 @@ Float nvim__id_float(Float flt) { return flt; } + +/// Gets a list of dictionaries representing attached UIs. +/// +/// @return Array of UI dictionaries +Array nvim_list_uis(void) + FUNC_API_SINCE(4) +{ + return ui_array(); +} -- cgit From dbad797edd4636f830abd7ade1138a1a27ac30d2 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 11 Mar 2018 21:47:12 +0100 Subject: API: nvim_get_proc_children() ref https://github.com/libuv/libuv/pull/836 --- src/nvim/api/vim.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index dad67c5e4b..850f892c18 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -33,6 +33,7 @@ #include "nvim/syntax.h" #include "nvim/getchar.h" #include "nvim/os/input.h" +#include "nvim/os/process.h" #include "nvim/viml/parser/expressions.h" #include "nvim/viml/parser/parser.h" #include "nvim/ui.h" @@ -1478,3 +1479,36 @@ Array nvim_list_uis(void) { return ui_array(); } + +/// Gets the immediate children of process `pid`. +/// +/// @return Array of child process ids, or empty array if process not found. +Array nvim_get_proc_children(Integer pid, Error *err) + FUNC_API_SINCE(4) +{ + Array proc_array = ARRAY_DICT_INIT; + int *proc_list = NULL; + + if (pid <= 0 || pid > INT_MAX) { + api_set_error(err, kErrorTypeException, "Invalid pid: %d", pid); + goto end; + } + + size_t proc_count; + int rv = os_proc_children((int)pid, &proc_list, &proc_count); + if (rv == 1) { + goto end; // Process not found; return empty list. + } else if (rv != 0) { + api_set_error(err, kErrorTypeException, + "Failed to get process children. pid=%d error=%d", pid, rv); + goto end; + } + + for (size_t i = 0; i < proc_count; i++) { + ADD(proc_array, INTEGER_OBJ(proc_list[i])); + } + +end: + xfree(proc_list); + return proc_array; +} -- cgit From 12af7016e23e7b7f507dc99a1b73e64d0bb5ccf3 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 14 Mar 2018 23:26:37 +0100 Subject: nvim_get_proc_children: fallback to shell MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /proc/…/children may be unavailable because of an unset kernel option. Fallback to `pgrep` invoked in a shell. --- src/nvim/api/vim.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 850f892c18..9f1f395c28 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1482,7 +1482,7 @@ Array nvim_list_uis(void) /// Gets the immediate children of process `pid`. /// -/// @return Array of child process ids, or empty array if process not found. +/// @return Array of child process ids. Empty array if process not found. Array nvim_get_proc_children(Integer pid, Error *err) FUNC_API_SINCE(4) { @@ -1490,17 +1490,27 @@ Array nvim_get_proc_children(Integer pid, Error *err) int *proc_list = NULL; if (pid <= 0 || pid > INT_MAX) { - api_set_error(err, kErrorTypeException, "Invalid pid: %d", pid); + api_set_error(err, kErrorTypeException, "Invalid pid: %" PRId64, pid); goto end; } size_t proc_count; int rv = os_proc_children((int)pid, &proc_list, &proc_count); - if (rv == 1) { - goto end; // Process not found; return empty list. - } else if (rv != 0) { - api_set_error(err, kErrorTypeException, - "Failed to get process children. pid=%d error=%d", pid, rv); + if (rv != 0) { + // syscall failed (possibly because of kernel options), try shelling out. + Array a = ARRAY_DICT_INIT; + ADD(a, INTEGER_OBJ(pid)); + String s = cstr_to_string("return vim._os_proc_children(select(1, ...))"); + Object o = nvim_execute_lua(s, a, err); + api_free_string(s); + api_free_array(a); + if (o.type == kObjectTypeArray) { + proc_array = o.data.array; + } else if (!ERROR_SET(err)) { + api_set_error(err, kErrorTypeException, + "Failed to get process children. pid=%" PRId64 " error=%d", + pid, rv); + } goto end; } -- cgit From a034d4b69d6032b3431c10b8a11c998551700fc2 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 16 Mar 2018 05:13:38 +0100 Subject: API: nvim_get_proc() TODO: "exepath" field (win32: QueryFullProcessImageName()) On unix-likes `ps` is used because the platform-specific APIs are a nightmare. For reference, below is a (incomplete) attempt: diff --git a/src/nvim/os/process.c b/src/nvim/os/process.c index 09769925aca5..99afbbf290c1 100644 --- a/src/nvim/os/process.c +++ b/src/nvim/os/process.c @@ -208,3 +210,60 @@ int os_proc_children(int ppid, int **proc_list, size_t *proc_count) return 0; } +/// Gets various properties of the process identified by `pid`. +/// +/// @param pid Process to inspect. +/// @return Map of process properties, empty on error. +Dictionary os_proc_info(int pid) +{ + Dictionary pinfo = ARRAY_DICT_INIT; +#ifdef WIN32 + +#elif defined(__APPLE__) + char buf[PROC_PIDPATHINFO_MAXSIZE]; + if (proc_pidpath(pid, buf, sizeof(buf))) { + name = getName(buf); + PUT(pinfo, "exepath", STRING_OBJ(cstr_to_string(buf))); + return name; + } else { + ILOG("proc_pidpath() failed for pid: %d", pid); + } +#elif defined(BSD) +# if defined(__FreeBSD__) +# define KP_COMM(o) o.ki_comm +# else +# define KP_COMM(o) o.p_comm +# endif + struct kinfo_proc *proc = kinfo_getproc(pid); + if (proc) { + PUT(pinfo, "name", cstr_to_string(KP_COMM(proc))); + xfree(proc); + } else { + ILOG("kinfo_getproc() failed for pid: %d", pid); + } + +#elif defined(__linux__) + char fname[256] = { 0 }; + char buf[MAXPATHL]; + snprintf(fname, sizeof(fname), "/proc/%d/comm", pid); + FILE *fp = fopen(fname, "r"); + // FileDescriptor *f = file_open_new(&error, fname, kFileReadOnly, 0); + // ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf, + // const size_t size) + if (fp == NULL) { + ILOG("fopen() of /proc/%d/comm failed", pid); + } else { + size_t n = fread(buf, sizeof(char), sizeof(buf) - 1, fp); + if (n == 0) { + WLOG("fread() of /proc/%d/comm failed", pid); + } else { + size_t end = MIN(sizeof(buf) - 1, n); + end = (end > 0 && buf[end - 1] == '\n') ? end - 1 : end; + buf[end] = '\0'; + PUT(pinfo, "name", STRING_OBJ(cstr_to_string(buf))); + } + } + fclose(fp); +#endif + return pinfo; +} --- src/nvim/api/vim.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 9f1f395c28..962081cc23 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1482,11 +1482,11 @@ Array nvim_list_uis(void) /// Gets the immediate children of process `pid`. /// -/// @return Array of child process ids. Empty array if process not found. +/// @return Array of child process ids, empty if process not found. Array nvim_get_proc_children(Integer pid, Error *err) FUNC_API_SINCE(4) { - Array proc_array = ARRAY_DICT_INIT; + Array rvobj = ARRAY_DICT_INIT; int *proc_list = NULL; if (pid <= 0 || pid > INT_MAX) { @@ -1498,6 +1498,7 @@ Array nvim_get_proc_children(Integer pid, Error *err) int rv = os_proc_children((int)pid, &proc_list, &proc_count); if (rv != 0) { // syscall failed (possibly because of kernel options), try shelling out. + DLOG("fallback to vim._os_proc_children()"); Array a = ARRAY_DICT_INIT; ADD(a, INTEGER_OBJ(pid)); String s = cstr_to_string("return vim._os_proc_children(select(1, ...))"); @@ -1505,7 +1506,7 @@ Array nvim_get_proc_children(Integer pid, Error *err) api_free_string(s); api_free_array(a); if (o.type == kObjectTypeArray) { - proc_array = o.data.array; + rvobj = o.data.array; } else if (!ERROR_SET(err)) { api_set_error(err, kErrorTypeException, "Failed to get process children. pid=%" PRId64 " error=%d", @@ -1515,10 +1516,49 @@ Array nvim_get_proc_children(Integer pid, Error *err) } for (size_t i = 0; i < proc_count; i++) { - ADD(proc_array, INTEGER_OBJ(proc_list[i])); + ADD(rvobj, INTEGER_OBJ(proc_list[i])); } end: xfree(proc_list); - return proc_array; + return rvobj; +} + +/// Gets info describing process `pid`. +/// +/// @return Map of process properties, or NIL if process not found. +Object nvim_get_proc(Integer pid, Error *err) + FUNC_API_SINCE(4) +{ + Object rvobj = OBJECT_INIT; + rvobj.data.dictionary = (Dictionary)ARRAY_DICT_INIT; + rvobj.type = kObjectTypeDictionary; + + if (pid <= 0 || pid > INT_MAX) { + api_set_error(err, kErrorTypeException, "Invalid pid: %" PRId64, pid); + return NIL; + } +#ifdef WIN32 + rvobj.data.dictionary = os_proc_info((int)pid); + if (rvobj.data.dictionary.size == 0) { // Process not found. + return NIL; + } +#else + // Cross-platform process info APIs are miserable, so use `ps` instead. + Array a = ARRAY_DICT_INIT; + ADD(a, INTEGER_OBJ(pid)); + String s = cstr_to_string("return vim._os_proc_info(select(1, ...))"); + Object o = nvim_execute_lua(s, a, err); + api_free_string(s); + api_free_array(a); + if (o.type == kObjectTypeArray && o.data.array.size == 0) { + return NIL; // Process not found. + } else if (o.type == kObjectTypeDictionary) { + rvobj.data.dictionary = o.data.dictionary; + } else if (!ERROR_SET(err)) { + api_set_error(err, kErrorTypeException, + "Failed to get process info. pid=%" PRId64, pid); + } +#endif + return rvobj; } -- cgit From 960f09362539a65bedebe2d4e4a878546df66273 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 16 Mar 2018 07:29:30 +0100 Subject: build/MSVC: fix "C4028: formal parameter different from declaration" --- src/nvim/api/private/defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h index 2144c80d6a..390b7e8363 100644 --- a/src/nvim/api/private/defs.h +++ b/src/nvim/api/private/defs.h @@ -47,7 +47,7 @@ typedef enum { /// Internal call from lua code #define LUA_INTERNAL_CALL (VIML_INTERNAL_CALL + 1) -static inline bool is_internal_call(uint64_t channel_id) +static inline bool is_internal_call(const uint64_t channel_id) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_CONST; /// Check whether call is internal -- cgit From 26b84a8b3e99d9dce2ad9f34e1663f119cd1c558 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 16 Mar 2018 07:34:27 +0100 Subject: build/MSVC: fix "C4003: not enough actual parameters for macro" For the case of TV_DICTITEM_STRUCT, we can't just pass `1` because: https://github.com/neovim/neovim/pull/8142#discussion_r175262436 > this variant will trigger array overrun warnings from various static analyzers. --- src/nvim/api/private/helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 65c306d4b1..1115faaeaf 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -567,7 +567,7 @@ static inline void typval_encode_dict_end(EncodedData *const edata) typval_encode_dict_end(edata) #define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ - TYPVAL_ENCODE_CONV_NIL() + TYPVAL_ENCODE_CONV_NIL(val) #define TYPVAL_ENCODE_SCOPE static #define TYPVAL_ENCODE_NAME object -- cgit From 79b4b6fc86497fcb7b3f986e98cbf03f93b5b082 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 21 Jan 2018 03:27:48 +0300 Subject: *: Make sure that !did_throw implies !current_exception Fixes #7876 --- src/nvim/api/private/helpers.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 1115faaeaf..29024a471f 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -47,6 +47,9 @@ typedef struct { /// @param[out] tstate Location where try state should be saved. void try_enter(TryState *const tstate) { + // TODO(ZyX-I): Check whether try_enter()/try_leave() may use + // enter_cleanup()/leave_cleanup(). Or + // save_dbg_stuff()/restore_dbg_stuff(). *tstate = (TryState) { .current_exception = current_exception, .msg_list = (const struct msglist *const *)msg_list, -- cgit From 201a4ef11cc69d7d7c384db4d937d0d413811577 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 25 Mar 2018 15:13:05 +0300 Subject: *: Replace did_throw checks with current_exception checks Removes obsolete did_throw after that. --- src/nvim/api/private/helpers.c | 8 ++------ src/nvim/api/private/helpers.h | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'src/nvim/api') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 29024a471f..12a4279dd7 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -56,7 +56,6 @@ void try_enter(TryState *const tstate) .private_msg_list = NULL, .trylevel = trylevel, .got_int = got_int, - .did_throw = did_throw, .need_rethrow = need_rethrow, .did_emsg = did_emsg, }; @@ -64,7 +63,6 @@ void try_enter(TryState *const tstate) current_exception = NULL; trylevel = 1; got_int = false; - did_throw = false; need_rethrow = false; did_emsg = false; } @@ -85,7 +83,6 @@ bool try_leave(const TryState *const tstate, Error *const err) assert(trylevel == 0); assert(!need_rethrow); assert(!got_int); - assert(!did_throw); assert(!did_emsg); assert(msg_list == &tstate->private_msg_list); assert(*msg_list == NULL); @@ -94,7 +91,6 @@ bool try_leave(const TryState *const tstate, Error *const err) current_exception = tstate->current_exception; trylevel = tstate->trylevel; got_int = tstate->got_int; - did_throw = tstate->did_throw; need_rethrow = tstate->need_rethrow; did_emsg = tstate->did_emsg; return ret; @@ -130,7 +126,7 @@ bool try_end(Error *err) did_emsg = false; if (got_int) { - if (did_throw) { + if (current_exception) { // If we got an interrupt, discard the current exception discard_current_exception(); } @@ -149,7 +145,7 @@ bool try_end(Error *err) if (should_free) { xfree(msg); } - } else if (did_throw) { + } else if (current_exception) { api_set_error(err, kErrorTypeException, "%s", current_exception->value); discard_current_exception(); } diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index 87f334ac30..0634764f13 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -93,7 +93,6 @@ typedef struct { const struct msglist *const *msg_list; int trylevel; int got_int; - int did_throw; int need_rethrow; int did_emsg; } TryState; -- cgit