refactor(api): move option code to own file

This commit is contained in:
bfredl
2022-06-12 00:37:39 +02:00
parent 502f03fc06
commit 4a275e3291
7 changed files with 519 additions and 490 deletions

View File

@@ -24,6 +24,7 @@
#include "nvim/api/autocmd.h"
#include "nvim/api/buffer.h"
#include "nvim/api/extmark.h"
#include "nvim/api/options.h"
#include "nvim/api/tabpage.h"
#include "nvim/api/ui.h"
#include "nvim/api/vim.h"

View File

@@ -32,8 +32,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/option.h"
#include "nvim/option_defs.h"
#include "nvim/ui.h"
#include "nvim/version.h"
#include "nvim/vim.h"
@@ -262,151 +260,6 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva
return rv;
}
/// Gets the value of a global or local(buffer, window) option.
///
/// @param from If `type` is `SREQ_WIN` or `SREQ_BUF`, this must be a pointer
/// to the window or buffer.
/// @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
/// @return the option value
Object get_option_from(void *from, int type, String name, Error *err)
{
Object rv = OBJECT_INIT;
if (name.size == 0) {
api_set_error(err, kErrorTypeValidation, "Empty option name");
return rv;
}
// Return values
int64_t numval;
char *stringval = NULL;
int flags = get_option_value_strict(name.data, &numval, &stringval,
type, from);
if (!flags) {
api_set_error(err, kErrorTypeValidation, "Invalid option name: '%s'",
name.data);
return rv;
}
if (flags & SOPT_BOOL) {
rv.type = kObjectTypeBoolean;
rv.data.boolean = numval ? true : false;
} else if (flags & SOPT_NUM) {
rv.type = kObjectTypeInteger;
rv.data.integer = numval;
} else if (flags & SOPT_STRING) {
if (stringval) {
rv.type = kObjectTypeString;
rv.data.string.data = stringval;
rv.data.string.size = strlen(stringval);
} else {
api_set_error(err, kErrorTypeException,
"Failed to get value for option '%s'",
name.data);
}
} else {
api_set_error(err,
kErrorTypeException,
"Unknown type for option '%s'",
name.data);
}
return rv;
}
/// Sets the value of a global or local(buffer, window) option.
///
/// @param to If `type` is `SREQ_WIN` or `SREQ_BUF`, this must be a pointer
/// to the window or buffer.
/// @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(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");
return;
}
int flags = get_option_value_strict(name.data, NULL, NULL, type, to);
if (flags == 0) {
api_set_error(err, kErrorTypeValidation, "Invalid option name '%s'",
name.data);
return;
}
if (value.type == kObjectTypeNil) {
if (type == SREQ_GLOBAL) {
api_set_error(err, kErrorTypeException, "Cannot unset option '%s'",
name.data);
return;
} else if (!(flags & SOPT_GLOBAL)) {
api_set_error(err,
kErrorTypeException,
"Cannot unset option '%s' "
"because it doesn't have a global value",
name.data);
return;
} else {
unset_global_local_option(name.data, to);
return;
}
}
int numval = 0;
char *stringval = NULL;
if (flags & SOPT_BOOL) {
if (value.type != kObjectTypeBoolean) {
api_set_error(err,
kErrorTypeValidation,
"Option '%s' requires a Boolean value",
name.data);
return;
}
numval = value.data.boolean;
} else if (flags & SOPT_NUM) {
if (value.type != kObjectTypeInteger) {
api_set_error(err, kErrorTypeValidation,
"Option '%s' requires an integer value",
name.data);
return;
}
if (value.data.integer > INT_MAX || value.data.integer < INT_MIN) {
api_set_error(err, kErrorTypeValidation,
"Value for option '%s' is out of range",
name.data);
return;
}
numval = (int)value.data.integer;
} else {
if (value.type != kObjectTypeString) {
api_set_error(err, kErrorTypeValidation,
"Option '%s' requires a string value",
name.data);
return;
}
stringval = value.data.string.data;
}
WITH_SCRIPT_CONTEXT(channel_id, {
const int opt_flags = (type == SREQ_WIN && !(flags & SOPT_GLOBAL))
? 0 : (type == SREQ_GLOBAL)
? OPT_GLOBAL : OPT_LOCAL;
set_option_value_for(name.data, numval, stringval,
opt_flags, type, to, err);
});
}
buf_T *find_buffer_by_handle(Buffer buffer, Error *err)
{
if (buffer == 0) {
@@ -1035,59 +888,6 @@ Object copy_object(Object obj)
}
}
void set_option_value_for(char *key, long numval, char *stringval, int opt_flags, int opt_type,
void *from, 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 (try_end(err)) {
return;
}
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);
}
}
void api_set_error(Error *err, ErrorType errType, const char *format, ...)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PRINTF(3, 4)
{