aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorb-r-o-c-k <brockmammen@gmail.com>2018-04-29 21:02:17 -0500
committerb-r-o-c-k <brockmammen@gmail.com>2018-05-03 21:05:20 -0500
commit7170de19714acd5efa6979ef94de2a29e41d6173 (patch)
treeaef99101c9b9926704fdc0ec59ee7102af26631e
parent4744142fad9209a1adaa190b9bf16ddcbcb67ca9 (diff)
downloadrneovim-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.c5
-rw-r--r--src/nvim/api/private/helpers.c25
-rw-r--r--src/nvim/api/vim.c4
-rw-r--r--src/nvim/api/window.c5
-rw-r--r--src/nvim/buffer_defs.h4
-rw-r--r--src/nvim/eval.c19
-rw-r--r--src/nvim/ex_cmds2.c42
-rw-r--r--src/nvim/globals.h4
-rw-r--r--src/nvim/option.c18
-rw-r--r--src/nvim/option_defs.h7
-rw-r--r--test/functional/api/vim_spec.lua15
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()