diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/nvim/CMakeLists.txt | 20 | ||||
-rw-r--r-- | src/nvim/api/options.c | 203 | ||||
-rw-r--r-- | src/nvim/testdir/test_mksession.vim | 18 |
3 files changed, 95 insertions, 146 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index f465d911f9..37f3aa1a23 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -82,10 +82,10 @@ set(LINT_SUPPRESSES_ARCHIVE ${LINT_SUPPRESSES_ROOT}/errors.tar.gz) set(LINT_SUPPRESSES_TOUCH_FILE "${TOUCHES_DIR}/unpacked-clint-errors-archive") set(LINT_SUPPRESSES_INSTALL_SCRIPT "${PROJECT_SOURCE_DIR}/cmake/InstallClintErrors.cmake") -file(GLOB UNICODE_FILES ${UNICODE_DIR}/*.txt) -file(GLOB API_HEADERS api/*.h) +glob_wrapper(UNICODE_FILES ${UNICODE_DIR}/*.txt) +glob_wrapper(API_HEADERS api/*.h) list(REMOVE_ITEM API_HEADERS ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h) -file(GLOB MSGPACK_RPC_HEADERS msgpack_rpc/*.h) +glob_wrapper(MSGPACK_RPC_HEADERS msgpack_rpc/*.h) include_directories(${GENERATED_DIR}) include_directories(${CACHED_GENERATED_DIR}) @@ -97,10 +97,10 @@ file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}) file(MAKE_DIRECTORY ${LINT_SUPPRESSES_ROOT}) file(MAKE_DIRECTORY ${LINT_SUPPRESSES_ROOT}/src) -file(GLOB NVIM_SOURCES *.c) -file(GLOB NVIM_HEADERS *.h) -file(GLOB EXTERNAL_SOURCES ../xdiff/*.c ../mpack/*.c ../cjson/*.c) -file(GLOB EXTERNAL_HEADERS ../xdiff/*.h ../mpack/*.h ../cjson/*.h) +glob_wrapper(NVIM_SOURCES *.c) +glob_wrapper(NVIM_HEADERS *.h) +glob_wrapper(EXTERNAL_SOURCES ../xdiff/*.c ../mpack/*.c ../cjson/*.c) +glob_wrapper(EXTERNAL_HEADERS ../xdiff/*.h ../mpack/*.h ../cjson/*.h) foreach(subdir os @@ -120,13 +120,13 @@ foreach(subdir file(MAKE_DIRECTORY ${GENERATED_DIR}/${subdir}) file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/${subdir}) - file(GLOB sources ${subdir}/*.c) - file(GLOB headers ${subdir}/*.h) + glob_wrapper(sources ${subdir}/*.c) + glob_wrapper(headers ${subdir}/*.h) list(APPEND NVIM_SOURCES ${sources}) list(APPEND NVIM_HEADERS ${headers}) endforeach() -file(GLOB UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c) +glob_wrapper(UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c) # Sort file lists to ensure generated files are created in the same order from # build to build. 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; diff --git a/src/nvim/testdir/test_mksession.vim b/src/nvim/testdir/test_mksession.vim index c55ba391a5..cf90e416c4 100644 --- a/src/nvim/testdir/test_mksession.vim +++ b/src/nvim/testdir/test_mksession.vim @@ -363,21 +363,29 @@ func Test_mkview_open_folds() call append(0, ['a', 'b', 'c']) 1,3fold + write! Xtestfile + + call assert_notequal(-1, foldclosed(1)) + call assert_notequal(-1, foldclosed(2)) + call assert_notequal(-1, foldclosed(3)) + + " Save the view with folds closed + mkview! Xtestview + " zR affects 'foldlevel', make sure the option is applied after the folds " have been recreated. + " Open folds to ensure they get closed when restoring the view normal zR - write! Xtestfile call assert_equal(-1, foldclosed(1)) call assert_equal(-1, foldclosed(2)) call assert_equal(-1, foldclosed(3)) - mkview! Xtestview source Xtestview - call assert_equal(-1, foldclosed(1)) - call assert_equal(-1, foldclosed(2)) - call assert_equal(-1, foldclosed(3)) + call assert_notequal(-1, foldclosed(1)) + call assert_notequal(-1, foldclosed(2)) + call assert_notequal(-1, foldclosed(3)) call delete('Xtestview') call delete('Xtestfile') |