diff options
author | b-r-o-c-k <brockmammen@gmail.com> | 2018-04-29 21:02:17 -0500 |
---|---|---|
committer | b-r-o-c-k <brockmammen@gmail.com> | 2018-05-03 21:05:20 -0500 |
commit | 7170de19714acd5efa6979ef94de2a29e41d6173 (patch) | |
tree | aef99101c9b9926704fdc0ec59ee7102af26631e | |
parent | 4744142fad9209a1adaa190b9bf16ddcbcb67ca9 (diff) | |
download | rneovim-7170de19714acd5efa6979ef94de2a29e41d6173.tar.gz rneovim-7170de19714acd5efa6979ef94de2a29e41d6173.tar.bz2 rneovim-7170de19714acd5efa6979ef94de2a29e41d6173.zip |
api: Make nvim_set_option() update `:verbose set ...`
Make `:verbose set ...` show when an option was last modified by an
API client or Lua script/chunk. In the case of an API client, the
channel ID is displayed.
-rw-r--r-- | src/nvim/api/buffer.c | 5 | ||||
-rw-r--r-- | src/nvim/api/private/helpers.c | 25 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 4 | ||||
-rw-r--r-- | src/nvim/api/window.c | 5 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 4 | ||||
-rw-r--r-- | src/nvim/eval.c | 19 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.c | 42 | ||||
-rw-r--r-- | src/nvim/globals.h | 4 | ||||
-rw-r--r-- | src/nvim/option.c | 18 | ||||
-rw-r--r-- | src/nvim/option_defs.h | 7 | ||||
-rw-r--r-- | test/functional/api/vim_spec.lua | 15 |
11 files changed, 104 insertions, 44 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 6be981a18e..023f434f9d 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -581,7 +581,8 @@ Object nvim_buf_get_option(Buffer buffer, String name, Error *err) /// @param name Option name /// @param value Option value /// @param[out] err Error details, if any -void nvim_buf_set_option(Buffer buffer, String name, Object value, Error *err) +void nvim_buf_set_option(uint64_t channel_id, Buffer buffer, + String name, Object value, Error *err) FUNC_API_SINCE(1) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -590,7 +591,7 @@ void nvim_buf_set_option(Buffer buffer, String name, Object value, Error *err) return; } - set_option_to(buf, SREQ_BUF, name, value, err); + set_option_to(channel_id, buf, SREQ_BUF, name, value, err); } /// Gets the buffer number diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 12a4279dd7..72542ed3e4 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -326,7 +326,8 @@ Object get_option_from(void *from, int type, String name, Error *err) /// @param type One of `SREQ_GLOBAL`, `SREQ_WIN` or `SREQ_BUF` /// @param name The option name /// @param[out] err Details of an error that may have occurred -void set_option_to(void *to, int type, String name, Object value, Error *err) +void set_option_to(uint64_t channel_id, void *to, int type, + String name, Object value, Error *err) { if (name.size == 0) { api_set_error(err, kErrorTypeValidation, "Empty option name"); @@ -363,7 +364,8 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) } } - int opt_flags = (type == SREQ_GLOBAL) ? OPT_GLOBAL : OPT_LOCAL; + int numval = 0; + char *stringval = NULL; if (flags & SOPT_BOOL) { if (value.type != kObjectTypeBoolean) { @@ -374,8 +376,7 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) return; } - bool val = value.data.boolean; - set_option_value_for(name.data, val, NULL, opt_flags, type, to, err); + numval = value.data.boolean; } else if (flags & SOPT_NUM) { if (value.type != kObjectTypeInteger) { api_set_error(err, @@ -393,8 +394,7 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) return; } - int val = (int) value.data.integer; - set_option_value_for(name.data, val, NULL, opt_flags, type, to, err); + numval = (int)value.data.integer; } else { if (value.type != kObjectTypeString) { api_set_error(err, @@ -404,9 +404,18 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) return; } - set_option_value_for(name.data, 0, value.data.string.data, - opt_flags, type, to, err); + stringval = (char *)value.data.string.data; } + + const scid_T save_current_SID = current_SID; + current_SID = channel_id == LUA_INTERNAL_CALL ? SID_LUA : SID_API_CLIENT; + current_channel_id = channel_id; + + const int opt_flags = (type == SREQ_GLOBAL) ? OPT_GLOBAL : OPT_LOCAL; + set_option_value_for(name.data, numval, stringval, + opt_flags, type, to, err); + + current_SID = save_current_SID; } #define TYPVAL_ENCODE_ALLOW_SPECIALS false diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index af3d379870..46ec8fe10b 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -549,10 +549,10 @@ Object nvim_get_option(String name, Error *err) /// @param name Option name /// @param value New option value /// @param[out] err Error details, if any -void nvim_set_option(String name, Object value, Error *err) +void nvim_set_option(uint64_t channel_id, String name, Object value, Error *err) FUNC_API_SINCE(1) { - set_option_to(NULL, SREQ_GLOBAL, name, value, err); + set_option_to(channel_id, NULL, SREQ_GLOBAL, name, value, err); } /// Writes a message to the Vim output buffer. Does not append "\n", the diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index 9bc91ef8fb..abfa0dc20b 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -309,7 +309,8 @@ Object nvim_win_get_option(Window window, String name, Error *err) /// @param name Option name /// @param value Option value /// @param[out] err Error details, if any -void nvim_win_set_option(Window window, String name, Object value, Error *err) +void nvim_win_set_option(uint64_t channel_id, Window window, + String name, Object value, Error *err) FUNC_API_SINCE(1) { win_T *win = find_window_by_handle(window, err); @@ -318,7 +319,7 @@ void nvim_win_set_option(Window window, String name, Object value, Error *err) return; } - set_option_to(win, SREQ_WIN, name, value, err); + set_option_to(channel_id, win, SREQ_WIN, name, value, err); } /// Gets the window position in display cells. First position is zero. diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 8de4286216..c8c2cd732c 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -237,7 +237,7 @@ typedef struct { char_u *wo_winhl; # define w_p_winhl w_onebuf_opt.wo_winhl // 'winhighlight' - int wo_scriptID[WV_COUNT]; /* SIDs for window-local options */ + LastSet wo_scriptID[WV_COUNT]; /* SIDs for window-local options */ # define w_p_scriptID w_onebuf_opt.wo_scriptID } winopt_T; @@ -590,7 +590,7 @@ struct file_buffer { */ bool b_p_initialized; /* set when options initialized */ - int b_p_scriptID[BV_COUNT]; /* SIDs for buffer-local options */ + LastSet b_p_scriptID[BV_COUNT]; /* SIDs for buffer-local options */ int b_p_ai; ///< 'autoindent' int b_p_ai_nopaste; ///< b_p_ai saved for paste mode diff --git a/src/nvim/eval.c b/src/nvim/eval.c index cc29496968..c48c22fd96 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -22061,12 +22061,25 @@ int store_session_globals(FILE *fd) */ void last_set_msg(scid_T scriptID) { - if (scriptID != 0) { - char_u *p = home_replace_save(NULL, get_scriptname(scriptID)); + LastSet last_set; + last_set.script_id = scriptID; + option_last_set_msg(last_set); +} + +/// Displays where an option was last set. +/// +/// Should only be invoked when 'verbose' is non-zero. +void option_last_set_msg(LastSet last_set) +{ + if (last_set.script_id != 0) { + bool should_free; + char_u *p = get_scriptname(last_set, &should_free); verbose_enter(); MSG_PUTS(_("\n\tLast set from ")); MSG_PUTS(p); - xfree(p); + if (should_free) { + xfree(p); + } verbose_leave(); } } diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 821c050c50..96d2102156 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -3055,24 +3055,32 @@ void scriptnames_slash_adjust(void) # endif /// Get a pointer to a script name. Used for ":verbose set". -char_u *get_scriptname(scid_T id) -{ - if (id == SID_MODELINE) { - return (char_u *)_("modeline"); - } - if (id == SID_CMDARG) { - return (char_u *)_("--cmd argument"); - } - if (id == SID_CARG) { - return (char_u *)_("-c argument"); - } - if (id == SID_ENV) { - return (char_u *)_("environment variable"); - } - if (id == SID_ERROR) { - return (char_u *)_("error handler"); +char_u *get_scriptname(LastSet last_set, bool *should_free) +{ + *should_free = false; + + switch (last_set.script_id) { + case SID_MODELINE: + return (char_u *)_("modeline"); + case SID_CMDARG: + return (char_u *)_("--cmd argument"); + case SID_CARG: + return (char_u *)_("-c argument"); + case SID_ENV: + return (char_u *)_("environment variable"); + case SID_ERROR: + return (char_u *)_("error handler"); + case SID_LUA: + return (char_u *)_("Lua"); + case SID_API_CLIENT: + vim_snprintf((char *)IObuff, IOSIZE, + _("API client (channel id %" PRIu64 ")"), + last_set.channel_id); + return IObuff; + default: + *should_free = true; + return home_replace_save(NULL, SCRIPT_ITEM(last_set.script_id).sn_name); } - return SCRIPT_ITEM(id).sn_name; } # if defined(EXITFREE) diff --git a/src/nvim/globals.h b/src/nvim/globals.h index e02100e933..1d49d6d26c 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -397,9 +397,13 @@ EXTERN int garbage_collect_at_exit INIT(= FALSE); #define SID_ENV -4 /* for sourcing environment variable */ #define SID_ERROR -5 /* option was reset because of an error */ #define SID_NONE -6 /* don't set scriptID */ +#define SID_LUA -7 /* for Lua scripts/chunks */ +#define SID_API_CLIENT -8 /* for API clients */ /* ID of script being sourced or was sourced to define the current function. */ EXTERN scid_T current_SID INIT(= 0); +/* ID of the current channel making a client API call */ +EXTERN uint64_t current_channel_id INIT(= 0); EXTERN bool did_source_packages INIT(= false); diff --git a/src/nvim/option.c b/src/nvim/option.c index 48fd797ee9..a2120b9ab4 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -196,7 +196,7 @@ typedef struct vimoption { idopt_T indir; /* global option: PV_NONE; * local option: indirect option index */ char_u *def_val[2]; /* default values for variable (vi and vim) */ - scid_T scriptID; /* script in which the option was last set */ + LastSet last_set; /* script in which the option was last set */ # define SCRIPTID_INIT , 0 } vimoption_T; @@ -1368,12 +1368,12 @@ do_set ( if (p_verbose > 0) { /* Mention where the option was last set. */ if (varp == options[opt_idx].var) - last_set_msg(options[opt_idx].scriptID); + option_last_set_msg(options[opt_idx].last_set); else if ((int)options[opt_idx].indir & PV_WIN) - last_set_msg(curwin->w_p_scriptID[ + option_last_set_msg(curwin->w_p_scriptID[ (int)options[opt_idx].indir & PV_MASK]); else if ((int)options[opt_idx].indir & PV_BUF) - last_set_msg(curbuf->b_p_scriptID[ + option_last_set_msg(curbuf->b_p_scriptID[ (int)options[opt_idx].indir & PV_MASK]); } } else { @@ -3663,16 +3663,18 @@ static void set_option_scriptID_idx(int opt_idx, int opt_flags, int id) { int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0; int indir = (int)options[opt_idx].indir; + const LastSet last_set = { id, current_channel_id }; /* Remember where the option was set. For local options need to do that * in the buffer or window structure. */ - if (both || (opt_flags & OPT_GLOBAL) || (indir & (PV_BUF|PV_WIN)) == 0) - options[opt_idx].scriptID = id; + if (both || (opt_flags & OPT_GLOBAL) || (indir & (PV_BUF|PV_WIN)) == 0) { + options[opt_idx].last_set = last_set; + } if (both || (opt_flags & OPT_LOCAL)) { if (indir & PV_BUF) - curbuf->b_p_scriptID[indir & PV_MASK] = id; + curbuf->b_p_scriptID[indir & PV_MASK] = last_set; else if (indir & PV_WIN) - curwin->w_p_scriptID[indir & PV_MASK] = id; + curwin->w_p_scriptID[indir & PV_MASK] = last_set; } } diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index 66a49fd6e0..670af1cc76 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -3,6 +3,7 @@ #include "nvim/types.h" #include "nvim/macros.h" // For EXTERN +#include "eval/typval.h" // For scid_T // option_defs.h: definition of global variables for settable options @@ -821,4 +822,10 @@ enum { #define SB_MAX 100000 // Maximum 'scrollback' value. +/// Stores an identifier of a script or channel that last set an option. +typedef struct { + scid_T script_id; /// Script ID or one of SID_* special values. + uint64_t channel_id; /// Only used when script_id is SID_API_CLIENT. +} LastSet; + #endif // NVIM_OPTION_DEFS_H diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 718294d941..599280d684 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -291,6 +291,21 @@ describe('api', function() eq(false, status) ok(err:match('Invalid option name') ~= nil) end) + + it('updates where the option was last set from', function() + nvim('set_option', 'equalalways', false) + local status, rv = pcall(nvim, 'command_output', + 'verbose set equalalways?') + eq(true, status) + ok(nil ~= string.find(rv, 'noequalalways\n'.. + '\tLast set from API client %(channel id %d+%)')) + + nvim('execute_lua', 'vim.api.nvim_set_option("equalalways", true)', {}) + local status, rv = pcall(nvim, 'command_output', + 'verbose set equalalways?') + eq(true, status) + eq(' equalalways\n\tLast set from Lua', rv) + end) end) describe('nvim_{get,set}_current_buf, nvim_list_bufs', function() |