aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/options.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/api/options.c')
-rw-r--r--src/nvim/api/options.c186
1 files changed, 104 insertions, 82 deletions
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c
index 61d4becd32..19ce25f676 100644
--- a/src/nvim/api/options.c
+++ b/src/nvim/api/options.c
@@ -21,17 +21,73 @@
# include "api/options.c.generated.h"
#endif
+static int validate_option_value_args(Dict(option) *opts, int *scope, int *opt_type, void **from,
+ Error *err)
+{
+ if (opts->scope.type == kObjectTypeString) {
+ if (!strcmp(opts->scope.data.string.data, "local")) {
+ *scope = OPT_LOCAL;
+ } else if (!strcmp(opts->scope.data.string.data, "global")) {
+ *scope = OPT_GLOBAL;
+ } else {
+ api_set_error(err, kErrorTypeValidation, "invalid scope: must be 'local' or 'global'");
+ return FAIL;
+ }
+ } else if (HAS_KEY(opts->scope)) {
+ api_set_error(err, kErrorTypeValidation, "invalid value for key: scope");
+ return FAIL;
+ }
+
+ *opt_type = SREQ_GLOBAL;
+
+ if (opts->win.type == kObjectTypeInteger) {
+ *opt_type = SREQ_WIN;
+ *from = find_window_by_handle((int)opts->win.data.integer, err);
+ if (ERROR_SET(err)) {
+ return FAIL;
+ }
+ } else if (HAS_KEY(opts->win)) {
+ api_set_error(err, kErrorTypeValidation, "invalid value for key: win");
+ return FAIL;
+ }
+
+ if (opts->buf.type == kObjectTypeInteger) {
+ *scope = OPT_LOCAL;
+ *opt_type = SREQ_BUF;
+ *from = find_buffer_by_handle((int)opts->buf.data.integer, err);
+ if (ERROR_SET(err)) {
+ return FAIL;
+ }
+ } else if (HAS_KEY(opts->buf)) {
+ api_set_error(err, kErrorTypeValidation, "invalid value for key: buf");
+ return FAIL;
+ }
+
+ if (HAS_KEY(opts->scope) && HAS_KEY(opts->buf)) {
+ api_set_error(err, kErrorTypeValidation, "scope and buf cannot be used together");
+ return FAIL;
+ }
+
+ if (HAS_KEY(opts->win) && HAS_KEY(opts->buf)) {
+ api_set_error(err, kErrorTypeValidation, "buf and win cannot be used together");
+ return FAIL;
+ }
+
+ return OK;
+}
+
/// Gets the value of an option. The behavior of this function matches that of
/// |:set|: the local value of an option is returned if it exists; otherwise,
/// the global value is returned. Local values always correspond to the current
-/// buffer or window. To get a buffer-local or window-local option for a
-/// specific buffer or window, use |nvim_buf_get_option()| or
-/// |nvim_win_get_option()|.
+/// buffer or window, unless "buf" or "win" is set in {opts}.
///
/// @param name Option name
/// @param opts Optional parameters
-/// - scope: One of 'global' or 'local'. Analogous to
+/// - scope: One of "global" or "local". Analogous to
/// |:setglobal| and |:setlocal|, respectively.
+/// - win: |window-ID|. Used for getting window local options.
+/// - buf: Buffer number. Used for getting buffer local options.
+/// Implies {scope} is "local".
/// @param[out] err Error details, if any
/// @return Option value
Object nvim_get_option_value(String name, Dict(option) *opts, Error *err)
@@ -40,23 +96,21 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err)
Object rv = OBJECT_INIT;
int scope = 0;
- if (opts->scope.type == kObjectTypeString) {
- if (!strcmp(opts->scope.data.string.data, "local")) {
- scope = OPT_LOCAL;
- } else if (!strcmp(opts->scope.data.string.data, "global")) {
- scope = OPT_GLOBAL;
- } else {
- api_set_error(err, kErrorTypeValidation, "invalid scope: must be 'local' or 'global'");
- goto end;
- }
- } else if (HAS_KEY(opts->scope)) {
- api_set_error(err, kErrorTypeValidation, "invalid value for key: scope");
- goto end;
+ int opt_type = SREQ_GLOBAL;
+ void *from = NULL;
+ if (!validate_option_value_args(opts, &scope, &opt_type, &from, err)) {
+ return rv;
}
long numval = 0;
char *stringval = NULL;
- switch (get_option_value(name.data, &numval, &stringval, scope)) {
+ int result = access_option_value_for(name.data, &numval, &stringval, scope, opt_type, from,
+ true, err);
+ if (ERROR_SET(err)) {
+ return rv;
+ }
+
+ switch (result) {
case 0:
rv = STRING_OBJ(cstr_as_string(stringval));
break;
@@ -78,10 +132,9 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err)
break;
default:
api_set_error(err, kErrorTypeValidation, "unknown option '%s'", name.data);
- goto end;
+ return rv;
}
-end:
return rv;
}
@@ -103,47 +156,9 @@ void nvim_set_option_value(String name, Object value, Dict(option) *opts, Error
FUNC_API_SINCE(9)
{
int scope = 0;
- if (opts->scope.type == kObjectTypeString) {
- if (!strcmp(opts->scope.data.string.data, "local")) {
- scope = OPT_LOCAL;
- } else if (!strcmp(opts->scope.data.string.data, "global")) {
- scope = OPT_GLOBAL;
- } else {
- api_set_error(err, kErrorTypeValidation, "invalid scope: must be 'local' or 'global'");
- return;
- }
- } else if (HAS_KEY(opts->scope)) {
- api_set_error(err, kErrorTypeValidation, "invalid value for key: scope");
- return;
- }
-
int opt_type = SREQ_GLOBAL;
void *to = NULL;
-
- if (opts->win.type == kObjectTypeInteger) {
- opt_type = SREQ_WIN;
- to = find_window_by_handle((int)opts->win.data.integer, err);
- } else if (HAS_KEY(opts->win)) {
- api_set_error(err, kErrorTypeValidation, "invalid value for key: win");
- return;
- }
-
- if (opts->buf.type == kObjectTypeInteger) {
- scope = OPT_LOCAL;
- opt_type = SREQ_BUF;
- to = find_buffer_by_handle((int)opts->buf.data.integer, err);
- } else if (HAS_KEY(opts->buf)) {
- api_set_error(err, kErrorTypeValidation, "invalid value for key: buf");
- return;
- }
-
- if (HAS_KEY(opts->scope) && HAS_KEY(opts->buf)) {
- api_set_error(err, kErrorTypeValidation, "scope and buf cannot be used together");
- return;
- }
-
- if (HAS_KEY(opts->win) && HAS_KEY(opts->buf)) {
- api_set_error(err, kErrorTypeValidation, "buf and win cannot be used together");
+ if (!validate_option_value_args(opts, &scope, &opt_type, &to, err)) {
return;
}
@@ -168,7 +183,7 @@ void nvim_set_option_value(String name, Object value, Dict(option) *opts, Error
return;
}
- set_option_value_for(name.data, numval, stringval, scope, opt_type, to, err);
+ access_option_value_for(name.data, &numval, &stringval, scope, opt_type, to, false, err);
}
/// Gets the option information for all options.
@@ -405,7 +420,7 @@ void set_option_to(uint64_t channel_id, void *to, int type, String name, Object
}
}
- int numval = 0;
+ long numval = 0;
char *stringval = NULL;
if (flags & SOPT_BOOL) {
@@ -450,16 +465,34 @@ void set_option_to(uint64_t channel_id, void *to, int type, String name, Object
? 0 : (type == SREQ_GLOBAL)
? OPT_GLOBAL : OPT_LOCAL;
- set_option_value_for(name.data, numval, stringval,
- opt_flags, type, to, err);
+ access_option_value_for(name.data, &numval, &stringval, opt_flags, type, to, false, err);
});
}
-void set_option_value_for(char *key, long numval, char *stringval, int opt_flags, int opt_type,
- void *from, Error *err)
+static int access_option_value(char *key, long *numval, char **stringval, int opt_flags, bool get,
+ Error *err)
+{
+ if (get) {
+ return get_option_value(key, numval, stringval, opt_flags);
+ } else {
+ char *errmsg;
+ if ((errmsg = set_option_value(key, *numval, *stringval, opt_flags))) {
+ if (try_end(err)) {
+ return 0;
+ }
+
+ api_set_error(err, kErrorTypeException, "%s", errmsg);
+ }
+ return 0;
+ }
+}
+
+static int access_option_value_for(char *key, long *numval, char **stringval, int opt_flags,
+ int opt_type, void *from, bool get, Error *err)
{
switchwin_T switchwin;
aco_save_T aco;
+ int result = 0;
try_start();
switch (opt_type) {
@@ -468,42 +501,31 @@ void set_option_value_for(char *key, long numval, char *stringval, int opt_flags
== FAIL) {
restore_win_noblock(&switchwin, true);
if (try_end(err)) {
- return;
+ return result;
}
api_set_error(err,
kErrorTypeException,
"Problem while switching windows");
- return;
+ return result;
}
- set_option_value_err(key, numval, stringval, opt_flags, err);
+ result = access_option_value(key, numval, stringval, opt_flags, get, err);
restore_win_noblock(&switchwin, true);
break;
case SREQ_BUF:
aucmd_prepbuf(&aco, (buf_T *)from);
- set_option_value_err(key, numval, stringval, opt_flags, err);
+ result = access_option_value(key, numval, stringval, opt_flags, get, err);
aucmd_restbuf(&aco);
break;
case SREQ_GLOBAL:
- set_option_value_err(key, numval, stringval, opt_flags, err);
+ result = access_option_value(key, numval, stringval, opt_flags, get, err);
break;
}
if (ERROR_SET(err)) {
- return;
+ return result;
}
try_end(err);
-}
-static void set_option_value_err(char *key, long numval, char *stringval, int opt_flags, Error *err)
-{
- char *errmsg;
-
- if ((errmsg = set_option_value(key, numval, stringval, opt_flags))) {
- if (try_end(err)) {
- return;
- }
-
- api_set_error(err, kErrorTypeException, "%s", errmsg);
- }
+ return result;
}