diff options
author | Lewis Russell <lewis6991@gmail.com> | 2023-03-15 23:30:14 +0000 |
---|---|---|
committer | Lewis Russell <lewis6991@gmail.com> | 2023-03-20 10:00:52 +0000 |
commit | e1db0e35e4d5859b96e6aff882df62d6c714b569 (patch) | |
tree | 8f6356c6a7cf6975c7bf26ad81fb3436ce1f90ae /src/nvim/api/options.c | |
parent | 84027f7515b8ee6f818462f105882fc0052783c4 (diff) | |
download | rneovim-e1db0e35e4d5859b96e6aff882df62d6c714b569.tar.gz rneovim-e1db0e35e4d5859b96e6aff882df62d6c714b569.tar.bz2 rneovim-e1db0e35e4d5859b96e6aff882df62d6c714b569.zip |
feat(api): add filetype option nvim_get_option_value
- Also adjust the expr-mapping behaviour so normal commands and text
changes are allowed in internal dummy buffers.
Diffstat (limited to 'src/nvim/api/options.c')
-rw-r--r-- | src/nvim/api/options.c | 72 |
1 files changed, 69 insertions, 3 deletions
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c index 2d9ffcba06..a0351cc6cd 100644 --- a/src/nvim/api/options.c +++ b/src/nvim/api/options.c @@ -24,7 +24,7 @@ #endif static int validate_option_value_args(Dict(option) *opts, int *scope, int *opt_type, void **from, - Error *err) + char **filetype, Error *err) { if (HAS_KEY(opts->scope)) { VALIDATE_T("scope", kObjectTypeString, opts->scope.type, { @@ -44,6 +44,14 @@ static int validate_option_value_args(Dict(option) *opts, int *scope, int *opt_t *opt_type = SREQ_GLOBAL; + if (filetype != NULL && HAS_KEY(opts->filetype)) { + VALIDATE_T("scope", kObjectTypeString, opts->filetype.type, { + return FAIL; + }); + + *filetype = opts->filetype.data.string.data; + } + if (HAS_KEY(opts->win)) { VALIDATE_T("win", kObjectTypeInteger, opts->win.type, { return FAIL; @@ -69,10 +77,17 @@ static int validate_option_value_args(Dict(option) *opts, int *scope, int *opt_t } } + VALIDATE((!HAS_KEY(opts->filetype) + || !(HAS_KEY(opts->buf) || HAS_KEY(opts->scope) || HAS_KEY(opts->win))), + "%s", "cannot use 'filetype' with 'scope', 'buf' or 'win'", { + return FAIL; + }); + VALIDATE((!HAS_KEY(opts->scope) || !HAS_KEY(opts->buf)), "%s", "cannot use both 'scope' and 'buf'", { return FAIL; }); + VALIDATE((!HAS_KEY(opts->win) || !HAS_KEY(opts->buf)), "%s", "cannot use both 'buf' and 'win'", { return FAIL; }); @@ -80,6 +95,30 @@ static int validate_option_value_args(Dict(option) *opts, int *scope, int *opt_t return OK; } +/// Create a dummy buffer and run the FileType autocmd on it. +static buf_T *do_ft_buf(char *filetype, aco_save_T *aco, Error *err) +{ + if (filetype == NULL) { + return NULL; + } + + // Allocate a buffer without putting it in the buffer list. + buf_T *ftbuf = buflist_new(NULL, NULL, 1, BLN_DUMMY); + if (ftbuf == NULL) { + api_set_error(err, kErrorTypeException, "Could not create internal buffer"); + return NULL; + } + + // Set curwin/curbuf to buf and save a few things. + aucmd_prepbuf(aco, ftbuf); + + ftbuf->b_p_ft = xstrdup(filetype); + + apply_autocmds(EVENT_FILETYPE, ftbuf->b_p_ft, ftbuf->b_fname, true, ftbuf); + + return ftbuf; +} + /// 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 @@ -92,6 +131,10 @@ static int validate_option_value_args(Dict(option) *opts, int *scope, int *opt_t /// - win: |window-ID|. Used for getting window local options. /// - buf: Buffer number. Used for getting buffer local options. /// Implies {scope} is "local". +/// - filetype: |filetype|. Used to get the default option for a +/// specific filetype. Cannot be used with any other option. +/// Note: this is expensive, it is recommended to cache this +/// value. /// @param[out] err Error details, if any /// @return Option value Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) @@ -102,14 +145,37 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) int scope = 0; int opt_type = SREQ_GLOBAL; void *from = NULL; - if (!validate_option_value_args(opts, &scope, &opt_type, &from, err)) { + char *filetype = NULL; + + if (!validate_option_value_args(opts, &scope, &opt_type, &from, &filetype, err)) { + return rv; + } + + aco_save_T aco; + + buf_T *ftbuf = do_ft_buf(filetype, &aco, err); + if (ERROR_SET(err)) { return rv; } + if (ftbuf != NULL) { + assert(!from); + from = ftbuf; + } + long numval = 0; char *stringval = NULL; getoption_T result = access_option_value_for(name.data, &numval, &stringval, scope, opt_type, from, true, err); + + if (ftbuf != NULL) { + // restore curwin/curbuf and a few other things + aucmd_restbuf(&aco); + + assert(curbuf != ftbuf); // safety check + wipe_buffer(ftbuf, false); + } + if (ERROR_SET(err)) { return rv; } @@ -164,7 +230,7 @@ void nvim_set_option_value(uint64_t channel_id, String name, Object value, Dict( int scope = 0; int opt_type = SREQ_GLOBAL; void *to = NULL; - if (!validate_option_value_args(opts, &scope, &opt_type, &to, err)) { + if (!validate_option_value_args(opts, &scope, &opt_type, &to, NULL, err)) { return; } |