mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 11:15:14 -07:00
Merge #8329 'API: Make nvim_set_option() update :verbose set …
'
This commit is contained in:
commit
273d2cd5d5
@ -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
|
||||
|
@ -324,7 +324,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");
|
||||
@ -361,7 +362,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) {
|
||||
@ -372,8 +374,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,
|
||||
@ -391,8 +392,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,
|
||||
@ -402,9 +402,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
|
||||
|
@ -683,10 +683,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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -22066,12 +22066,27 @@ 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));
|
||||
const LastSet last_set = (LastSet){
|
||||
.script_id = scriptID,
|
||||
.channel_id = 0,
|
||||
};
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
char_u *get_scriptname(LastSet last_set, bool *should_free)
|
||||
{
|
||||
if (id == SID_MODELINE) {
|
||||
return (char_u *)_("modeline");
|
||||
*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);
|
||||
}
|
||||
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");
|
||||
}
|
||||
return SCRIPT_ITEM(id).sn_name;
|
||||
}
|
||||
|
||||
# if defined(EXITFREE)
|
||||
|
@ -390,16 +390,20 @@ EXTERN int may_garbage_collect INIT(= FALSE);
|
||||
EXTERN int want_garbage_collect INIT(= FALSE);
|
||||
EXTERN int garbage_collect_at_exit INIT(= FALSE);
|
||||
|
||||
/* Special values for current_SID. */
|
||||
#define SID_MODELINE -1 /* when using a modeline */
|
||||
#define SID_CMDARG -2 /* for "--cmd" argument */
|
||||
#define SID_CARG -3 /* for "-c" argument */
|
||||
#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 */
|
||||
// Special values for current_SID.
|
||||
#define SID_MODELINE -1 // when using a modeline
|
||||
#define SID_CMDARG -2 // for "--cmd" argument
|
||||
#define SID_CARG -3 // for "-c" argument
|
||||
#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. */
|
||||
// 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);
|
||||
|
||||
|
@ -187,16 +187,16 @@ static long p_tw_nopaste;
|
||||
static long p_wm_nopaste;
|
||||
|
||||
typedef struct vimoption {
|
||||
char *fullname; /* full option name */
|
||||
char *shortname; /* permissible abbreviation */
|
||||
uint32_t flags; /* see below */
|
||||
char_u *var; /* global option: pointer to variable;
|
||||
* window-local option: VAR_WIN;
|
||||
* buffer-local option: global value */
|
||||
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 */
|
||||
char *fullname; // full option name
|
||||
char *shortname; // permissible abbreviation
|
||||
uint32_t flags; // see below
|
||||
char_u *var; // global option: pointer to variable;
|
||||
// window-local option: VAR_WIN;
|
||||
// buffer-local option: global value
|
||||
idopt_T indir; // global option: PV_NONE;
|
||||
// local option: indirect option index
|
||||
char_u *def_val[2]; // default values for variable (vi and vim)
|
||||
LastSet last_set; // script in which the option was last set
|
||||
# define SCRIPTID_INIT , 0
|
||||
} vimoption_T;
|
||||
|
||||
@ -1345,15 +1345,16 @@ do_set (
|
||||
if (opt_idx >= 0) {
|
||||
showoneopt(&options[opt_idx], opt_flags);
|
||||
if (p_verbose > 0) {
|
||||
/* Mention where the option was last set. */
|
||||
if (varp == options[opt_idx].var)
|
||||
last_set_msg(options[opt_idx].scriptID);
|
||||
else if ((int)options[opt_idx].indir & PV_WIN)
|
||||
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[
|
||||
(int)options[opt_idx].indir & PV_MASK]);
|
||||
// Mention where the option was last set.
|
||||
if (varp == options[opt_idx].var) {
|
||||
option_last_set_msg(options[opt_idx].last_set);
|
||||
} else if ((int)options[opt_idx].indir & PV_WIN) {
|
||||
option_last_set_msg(curwin->w_p_scriptID[
|
||||
(int)options[opt_idx].indir & PV_MASK]);
|
||||
} else if ((int)options[opt_idx].indir & PV_BUF) {
|
||||
option_last_set_msg(curbuf->b_p_scriptID[
|
||||
(int)options[opt_idx].indir & PV_MASK]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
errmsg = (char_u *)N_("E846: Key code not set");
|
||||
@ -3642,16 +3643,19 @@ 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;
|
||||
// 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].last_set = last_set;
|
||||
}
|
||||
if (both || (opt_flags & OPT_LOCAL)) {
|
||||
if (indir & PV_BUF)
|
||||
curbuf->b_p_scriptID[indir & PV_MASK] = id;
|
||||
else if (indir & PV_WIN)
|
||||
curwin->w_p_scriptID[indir & PV_MASK] = id;
|
||||
if (indir & PV_BUF) {
|
||||
curbuf->b_p_scriptID[indir & PV_MASK] = last_set;
|
||||
} else if (indir & PV_WIN) {
|
||||
curwin->w_p_scriptID[indir & PV_MASK] = last_set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
@ -819,4 +820,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
|
||||
|
@ -382,6 +382,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)', {})
|
||||
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()
|
||||
|
Loading…
Reference in New Issue
Block a user