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.c203
1 files changed, 72 insertions, 131 deletions
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c
index a35c7222ed..3067a6e6b4 100644
--- a/src/nvim/api/options.c
+++ b/src/nvim/api/options.c
@@ -21,75 +21,87 @@
# include "api/options.c.generated.h"
#endif
-/// 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, unless "buf" or "win" is set in {opts}.
-///
-/// @param name Option name
-/// @param opts Optional parameters
-/// - 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)
- FUNC_API_SINCE(9)
+static int validate_option_value_args(Dict(option) *opts, int *scope, int *opt_type, void **from,
+ 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;
+ *scope = OPT_LOCAL;
} else if (!strcmp(opts->scope.data.string.data, "global")) {
- scope = OPT_GLOBAL;
+ *scope = OPT_GLOBAL;
} else {
api_set_error(err, kErrorTypeValidation, "invalid scope: must be 'local' or 'global'");
- goto end;
+ return FAIL;
}
} else if (HAS_KEY(opts->scope)) {
api_set_error(err, kErrorTypeValidation, "invalid value for key: scope");
- goto end;
+ return FAIL;
}
- int opt_type = SREQ_GLOBAL;
- void *from = NULL;
+ *opt_type = SREQ_GLOBAL;
if (opts->win.type == kObjectTypeInteger) {
- opt_type = SREQ_WIN;
- from = find_window_by_handle((int)opts->win.data.integer, err);
+ *opt_type = SREQ_WIN;
+ *from = 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");
- goto end;
+ 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);
+ *scope = OPT_LOCAL;
+ *opt_type = SREQ_BUF;
+ *from = 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");
- goto end;
+ return FAIL;
}
if (HAS_KEY(opts->scope) && HAS_KEY(opts->buf)) {
api_set_error(err, kErrorTypeValidation, "scope and buf cannot be used together");
- goto end;
+ return FAIL;
}
if (HAS_KEY(opts->win) && HAS_KEY(opts->buf)) {
api_set_error(err, kErrorTypeValidation, "buf and win cannot be used together");
- goto end;
+ 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, unless "buf" or "win" is set in {opts}.
+///
+/// @param name Option name
+/// @param opts Optional parameters
+/// - 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)
+ FUNC_API_SINCE(9)
+{
+ Object rv = OBJECT_INIT;
+
+ int scope = 0;
+ 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;
- int result = get_option_value_for(name.data, &numval, &stringval, scope, opt_type, from, err);
+ int result = access_option_value_for(name.data, &numval, &stringval, scope, opt_type, from,
+ true, err);
if (ERROR_SET(err)) {
- goto end;
+ return rv;
}
switch (result) {
@@ -114,10 +126,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;
}
@@ -139,47 +150,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;
}
@@ -204,7 +177,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.
@@ -441,7 +414,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) {
@@ -486,66 +459,30 @@ 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)
{
- switchwin_T switchwin;
- aco_save_T aco;
-
- try_start();
- switch (opt_type) {
- case SREQ_WIN:
- if (switch_win_noblock(&switchwin, (win_T *)from, win_find_tabpage((win_T *)from), true)
- == FAIL) {
- restore_win_noblock(&switchwin, true);
+ 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;
+ return 0;
}
- api_set_error(err,
- kErrorTypeException,
- "Problem while switching windows");
- return;
- }
- set_option_value_err(key, numval, stringval, opt_flags, 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);
- aucmd_restbuf(&aco);
- break;
- case SREQ_GLOBAL:
- set_option_value_err(key, numval, stringval, opt_flags, err);
- break;
- }
-
- if (ERROR_SET(err)) {
- return;
- }
-
- 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);
}
-
- api_set_error(err, kErrorTypeException, "%s", errmsg);
+ return 0;
}
}
-int get_option_value_for(char *key, long *numval, char **stringval, int opt_flags, int opt_type,
- void *from, Error *err)
+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;
@@ -565,19 +502,23 @@ int get_option_value_for(char *key, long *numval, char **stringval, int opt_flag
"Problem while switching windows");
return result;
}
- result = get_option_value(key, numval, stringval, opt_flags);
+ 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);
- result = get_option_value(key, numval, stringval, opt_flags);
+ result = access_option_value(key, numval, stringval, opt_flags, get, err);
aucmd_restbuf(&aco);
break;
case SREQ_GLOBAL:
- result = get_option_value(key, numval, stringval, opt_flags);
+ result = access_option_value(key, numval, stringval, opt_flags, get, err);
break;
}
+ if (ERROR_SET(err)) {
+ return result;
+ }
+
try_end(err);
return result;