mirror of
https://github.com/neovim/neovim.git
synced 2024-12-23 20:55:18 -07:00
Merge pull request #24524 from bfredl/typed_keys
refactor(api): use typed keysets
This commit is contained in:
commit
3a21c3afe6
@ -134,6 +134,8 @@ The following new APIs and features were added.
|
||||
• `vim.fn.*`
|
||||
• `vim.api.*`
|
||||
|
||||
• Improved messages for type errors in `vim.api.*` calls (including `opts` params)
|
||||
|
||||
==============================================================================
|
||||
CHANGED FEATURES *news-changed*
|
||||
|
||||
|
302
runtime/lua/vim/_meta/api_keysets.lua
generated
302
runtime/lua/vim/_meta/api_keysets.lua
generated
@ -4,112 +4,112 @@
|
||||
error('Cannot require a meta file')
|
||||
|
||||
--- @class vim.api.keyset.clear_autocmds
|
||||
--- @field buffer any
|
||||
--- @field buffer integer
|
||||
--- @field event any
|
||||
--- @field group any
|
||||
--- @field pattern any
|
||||
|
||||
--- @class vim.api.keyset.cmd
|
||||
--- @field cmd any
|
||||
--- @field range any
|
||||
--- @field count any
|
||||
--- @field reg any
|
||||
--- @field bang any
|
||||
--- @field args any
|
||||
--- @field magic any
|
||||
--- @field mods any
|
||||
--- @field cmd string
|
||||
--- @field range any[]
|
||||
--- @field count integer
|
||||
--- @field reg string
|
||||
--- @field bang boolean
|
||||
--- @field args any[]
|
||||
--- @field magic table<string,any>
|
||||
--- @field mods table<string,any>
|
||||
--- @field nargs any
|
||||
--- @field addr any
|
||||
--- @field nextcmd any
|
||||
|
||||
--- @class vim.api.keyset.cmd_magic
|
||||
--- @field file any
|
||||
--- @field bar any
|
||||
--- @field file boolean
|
||||
--- @field bar boolean
|
||||
|
||||
--- @class vim.api.keyset.cmd_mods
|
||||
--- @field silent any
|
||||
--- @field emsg_silent any
|
||||
--- @field unsilent any
|
||||
--- @field filter any
|
||||
--- @field sandbox any
|
||||
--- @field noautocmd any
|
||||
--- @field browse any
|
||||
--- @field confirm any
|
||||
--- @field hide any
|
||||
--- @field horizontal any
|
||||
--- @field keepalt any
|
||||
--- @field keepjumps any
|
||||
--- @field keepmarks any
|
||||
--- @field keeppatterns any
|
||||
--- @field lockmarks any
|
||||
--- @field noswapfile any
|
||||
--- @field tab any
|
||||
--- @field verbose any
|
||||
--- @field vertical any
|
||||
--- @field split any
|
||||
--- @field silent boolean
|
||||
--- @field emsg_silent boolean
|
||||
--- @field unsilent boolean
|
||||
--- @field filter table<string,any>
|
||||
--- @field sandbox boolean
|
||||
--- @field noautocmd boolean
|
||||
--- @field browse boolean
|
||||
--- @field confirm boolean
|
||||
--- @field hide boolean
|
||||
--- @field horizontal boolean
|
||||
--- @field keepalt boolean
|
||||
--- @field keepjumps boolean
|
||||
--- @field keepmarks boolean
|
||||
--- @field keeppatterns boolean
|
||||
--- @field lockmarks boolean
|
||||
--- @field noswapfile boolean
|
||||
--- @field tab integer
|
||||
--- @field verbose integer
|
||||
--- @field vertical boolean
|
||||
--- @field split string
|
||||
|
||||
--- @class vim.api.keyset.cmd_mods_filter
|
||||
--- @field pattern any
|
||||
--- @field force any
|
||||
--- @field pattern string
|
||||
--- @field force boolean
|
||||
|
||||
--- @class vim.api.keyset.cmd_opts
|
||||
--- @field output any
|
||||
--- @field output boolean
|
||||
|
||||
--- @class vim.api.keyset.context
|
||||
--- @field types any
|
||||
--- @field types any[]
|
||||
|
||||
--- @class vim.api.keyset.create_augroup
|
||||
--- @field clear any
|
||||
|
||||
--- @class vim.api.keyset.create_autocmd
|
||||
--- @field buffer any
|
||||
--- @field buffer integer
|
||||
--- @field callback any
|
||||
--- @field command any
|
||||
--- @field desc any
|
||||
--- @field command string
|
||||
--- @field desc string
|
||||
--- @field group any
|
||||
--- @field nested any
|
||||
--- @field once any
|
||||
--- @field nested boolean
|
||||
--- @field once boolean
|
||||
--- @field pattern any
|
||||
|
||||
--- @class vim.api.keyset.echo_opts
|
||||
--- @field verbose any
|
||||
--- @field verbose boolean
|
||||
|
||||
--- @class vim.api.keyset.eval_statusline
|
||||
--- @field winid any
|
||||
--- @field maxwidth any
|
||||
--- @field fillchar any
|
||||
--- @field highlights any
|
||||
--- @field use_winbar any
|
||||
--- @field use_tabline any
|
||||
--- @field use_statuscol_lnum any
|
||||
--- @field winid integer
|
||||
--- @field maxwidth integer
|
||||
--- @field fillchar string
|
||||
--- @field highlights boolean
|
||||
--- @field use_winbar boolean
|
||||
--- @field use_tabline boolean
|
||||
--- @field use_statuscol_lnum integer
|
||||
|
||||
--- @class vim.api.keyset.exec_autocmds
|
||||
--- @field buffer any
|
||||
--- @field buffer integer
|
||||
--- @field group any
|
||||
--- @field modeline any
|
||||
--- @field modeline boolean
|
||||
--- @field pattern any
|
||||
--- @field data any
|
||||
|
||||
--- @class vim.api.keyset.exec_opts
|
||||
--- @field output any
|
||||
--- @field output boolean
|
||||
|
||||
--- @class vim.api.keyset.float_config
|
||||
--- @field row any
|
||||
--- @field col any
|
||||
--- @field width any
|
||||
--- @field height any
|
||||
--- @field anchor any
|
||||
--- @field relative any
|
||||
--- @field win any
|
||||
--- @field bufpos any
|
||||
--- @field external any
|
||||
--- @field focusable any
|
||||
--- @field zindex any
|
||||
--- @field row number
|
||||
--- @field col number
|
||||
--- @field width integer
|
||||
--- @field height integer
|
||||
--- @field anchor string
|
||||
--- @field relative string
|
||||
--- @field win integer
|
||||
--- @field bufpos any[]
|
||||
--- @field external boolean
|
||||
--- @field focusable boolean
|
||||
--- @field zindex integer
|
||||
--- @field border any
|
||||
--- @field title any
|
||||
--- @field title_pos any
|
||||
--- @field style any
|
||||
--- @field noautocmd any
|
||||
--- @field title_pos string
|
||||
--- @field style string
|
||||
--- @field noautocmd boolean
|
||||
|
||||
--- @class vim.api.keyset.get_autocmds
|
||||
--- @field event any
|
||||
@ -118,27 +118,27 @@ error('Cannot require a meta file')
|
||||
--- @field buffer any
|
||||
|
||||
--- @class vim.api.keyset.get_commands
|
||||
--- @field builtin any
|
||||
--- @field builtin boolean
|
||||
|
||||
--- @class vim.api.keyset.get_highlight
|
||||
--- @field id any
|
||||
--- @field name any
|
||||
--- @field link any
|
||||
--- @field id integer
|
||||
--- @field name string
|
||||
--- @field link boolean
|
||||
|
||||
--- @class vim.api.keyset.highlight
|
||||
--- @field bold any
|
||||
--- @field standout any
|
||||
--- @field strikethrough any
|
||||
--- @field underline any
|
||||
--- @field undercurl any
|
||||
--- @field underdouble any
|
||||
--- @field underdotted any
|
||||
--- @field underdashed any
|
||||
--- @field italic any
|
||||
--- @field reverse any
|
||||
--- @field altfont any
|
||||
--- @field nocombine any
|
||||
--- @field default_ any
|
||||
--- @field bold boolean
|
||||
--- @field standout boolean
|
||||
--- @field strikethrough boolean
|
||||
--- @field underline boolean
|
||||
--- @field undercurl boolean
|
||||
--- @field underdouble boolean
|
||||
--- @field underdotted boolean
|
||||
--- @field underdashed boolean
|
||||
--- @field italic boolean
|
||||
--- @field reverse boolean
|
||||
--- @field altfont boolean
|
||||
--- @field nocombine boolean
|
||||
--- @field default boolean
|
||||
--- @field cterm any
|
||||
--- @field foreground any
|
||||
--- @field fg any
|
||||
@ -150,100 +150,100 @@ error('Cannot require a meta file')
|
||||
--- @field sp any
|
||||
--- @field link any
|
||||
--- @field global_link any
|
||||
--- @field fallback any
|
||||
--- @field blend any
|
||||
--- @field fg_indexed any
|
||||
--- @field bg_indexed any
|
||||
--- @field fallback boolean
|
||||
--- @field blend integer
|
||||
--- @field fg_indexed boolean
|
||||
--- @field bg_indexed boolean
|
||||
|
||||
--- @class vim.api.keyset.highlight_cterm
|
||||
--- @field bold any
|
||||
--- @field standout any
|
||||
--- @field strikethrough any
|
||||
--- @field underline any
|
||||
--- @field undercurl any
|
||||
--- @field underdouble any
|
||||
--- @field underdotted any
|
||||
--- @field underdashed any
|
||||
--- @field italic any
|
||||
--- @field reverse any
|
||||
--- @field altfont any
|
||||
--- @field nocombine any
|
||||
--- @field bold boolean
|
||||
--- @field standout boolean
|
||||
--- @field strikethrough boolean
|
||||
--- @field underline boolean
|
||||
--- @field undercurl boolean
|
||||
--- @field underdouble boolean
|
||||
--- @field underdotted boolean
|
||||
--- @field underdashed boolean
|
||||
--- @field italic boolean
|
||||
--- @field reverse boolean
|
||||
--- @field altfont boolean
|
||||
--- @field nocombine boolean
|
||||
|
||||
--- @class vim.api.keyset.keymap
|
||||
--- @field noremap any
|
||||
--- @field nowait any
|
||||
--- @field silent any
|
||||
--- @field script any
|
||||
--- @field expr any
|
||||
--- @field unique any
|
||||
--- @field callback any
|
||||
--- @field desc any
|
||||
--- @field replace_keycodes any
|
||||
--- @field noremap boolean
|
||||
--- @field nowait boolean
|
||||
--- @field silent boolean
|
||||
--- @field script boolean
|
||||
--- @field expr boolean
|
||||
--- @field unique boolean
|
||||
--- @field callback function
|
||||
--- @field desc string
|
||||
--- @field replace_keycodes boolean
|
||||
|
||||
--- @class vim.api.keyset.option
|
||||
--- @field scope any
|
||||
--- @field win any
|
||||
--- @field buf any
|
||||
--- @field filetype any
|
||||
--- @field scope string
|
||||
--- @field win integer
|
||||
--- @field buf integer
|
||||
--- @field filetype string
|
||||
|
||||
--- @class vim.api.keyset.runtime
|
||||
--- @field is_lua any
|
||||
--- @field do_source any
|
||||
--- @field is_lua boolean
|
||||
--- @field do_source boolean
|
||||
|
||||
--- @class vim.api.keyset.set_decoration_provider
|
||||
--- @field on_start any
|
||||
--- @field on_buf any
|
||||
--- @field on_win any
|
||||
--- @field on_line any
|
||||
--- @field on_end any
|
||||
--- @field _on_hl_def any
|
||||
--- @field _on_spell_nav any
|
||||
--- @field on_start function
|
||||
--- @field on_buf function
|
||||
--- @field on_win function
|
||||
--- @field on_line function
|
||||
--- @field on_end function
|
||||
--- @field _on_hl_def function
|
||||
--- @field _on_spell_nav function
|
||||
|
||||
--- @class vim.api.keyset.set_extmark
|
||||
--- @field id any
|
||||
--- @field end_line any
|
||||
--- @field end_row any
|
||||
--- @field end_col any
|
||||
--- @field id integer
|
||||
--- @field end_line integer
|
||||
--- @field end_row integer
|
||||
--- @field end_col integer
|
||||
--- @field hl_group any
|
||||
--- @field virt_text any
|
||||
--- @field virt_text_pos any
|
||||
--- @field virt_text_win_col any
|
||||
--- @field virt_text_hide any
|
||||
--- @field hl_eol any
|
||||
--- @field hl_mode any
|
||||
--- @field ephemeral any
|
||||
--- @field priority any
|
||||
--- @field right_gravity any
|
||||
--- @field end_right_gravity any
|
||||
--- @field virt_lines any
|
||||
--- @field virt_lines_above any
|
||||
--- @field virt_lines_leftcol any
|
||||
--- @field strict any
|
||||
--- @field sign_text any
|
||||
--- @field virt_text any[]
|
||||
--- @field virt_text_pos string
|
||||
--- @field virt_text_win_col integer
|
||||
--- @field virt_text_hide boolean
|
||||
--- @field hl_eol boolean
|
||||
--- @field hl_mode string
|
||||
--- @field ephemeral boolean
|
||||
--- @field priority integer
|
||||
--- @field right_gravity boolean
|
||||
--- @field end_right_gravity boolean
|
||||
--- @field virt_lines any[]
|
||||
--- @field virt_lines_above boolean
|
||||
--- @field virt_lines_leftcol boolean
|
||||
--- @field strict boolean
|
||||
--- @field sign_text string
|
||||
--- @field sign_hl_group any
|
||||
--- @field number_hl_group any
|
||||
--- @field line_hl_group any
|
||||
--- @field cursorline_hl_group any
|
||||
--- @field conceal any
|
||||
--- @field spell any
|
||||
--- @field ui_watched any
|
||||
--- @field conceal string
|
||||
--- @field spell boolean
|
||||
--- @field ui_watched boolean
|
||||
|
||||
--- @class vim.api.keyset.user_command
|
||||
--- @field addr any
|
||||
--- @field bang any
|
||||
--- @field bar any
|
||||
--- @field bang boolean
|
||||
--- @field bar boolean
|
||||
--- @field complete any
|
||||
--- @field count any
|
||||
--- @field desc any
|
||||
--- @field force any
|
||||
--- @field keepscript any
|
||||
--- @field force boolean
|
||||
--- @field keepscript boolean
|
||||
--- @field nargs any
|
||||
--- @field preview any
|
||||
--- @field range any
|
||||
--- @field register_ any
|
||||
--- @field register boolean
|
||||
|
||||
--- @class vim.api.keyset.win_text_height
|
||||
--- @field start_row any
|
||||
--- @field end_row any
|
||||
--- @field start_vcol any
|
||||
--- @field end_vcol any
|
||||
--- @field start_row integer
|
||||
--- @field end_row integer
|
||||
--- @field start_vcol integer
|
||||
--- @field end_vcol integer
|
||||
|
@ -289,19 +289,18 @@ local function get_api_keysets_meta()
|
||||
|
||||
local ret = {} --- @type table<string, vim.EvalFn>
|
||||
|
||||
--- @type {[1]: string, [2]: {[1]: string, [2]: string}[] }[]
|
||||
--- @type {name: string, keys: string[], types: table<string,string>}[]
|
||||
local keysets = metadata.keysets
|
||||
|
||||
for _, keyset in ipairs(keysets) do
|
||||
local kname = keyset[1]
|
||||
local kdef = keyset[2]
|
||||
for _, field in ipairs(kdef) do
|
||||
field[2] = api_type(field[2])
|
||||
for _, k in ipairs(keysets) do
|
||||
local params = {}
|
||||
for _, key in ipairs(k.keys) do
|
||||
table.insert(params, {key, api_type(k.types[key] or 'any')})
|
||||
end
|
||||
ret[kname] = {
|
||||
ret[k.name] = {
|
||||
signature = 'NA',
|
||||
name = kname,
|
||||
params = kdef,
|
||||
name = k.name,
|
||||
params = params,
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "lauxlib.h"
|
||||
#include "nvim/api/autocmd.h"
|
||||
#include "nvim/api/private/defs.h"
|
||||
#include "nvim/api/private/dispatch.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/api/private/validate.h"
|
||||
#include "nvim/ascii.h"
|
||||
@ -125,7 +126,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
||||
});
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->event)) {
|
||||
if (HAS_KEY(opts, get_autocmds, event)) {
|
||||
check_event = true;
|
||||
|
||||
Object v = opts->event;
|
||||
@ -148,13 +149,13 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
||||
}
|
||||
}
|
||||
|
||||
VALIDATE((!HAS_KEY(opts->pattern) || !HAS_KEY(opts->buffer)),
|
||||
VALIDATE((!HAS_KEY(opts, get_autocmds, pattern) || !HAS_KEY(opts, get_autocmds, buffer)),
|
||||
"%s", "Cannot use both 'pattern' and 'buffer'", {
|
||||
goto cleanup;
|
||||
});
|
||||
|
||||
int pattern_filter_count = 0;
|
||||
if (HAS_KEY(opts->pattern)) {
|
||||
if (HAS_KEY(opts, get_autocmds, pattern)) {
|
||||
Object v = opts->pattern;
|
||||
if (v.type == kObjectTypeString) {
|
||||
pattern_filters[pattern_filter_count] = v.data.string.data;
|
||||
@ -209,7 +210,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
|
||||
snprintf(pattern_buflocal, BUFLOCAL_PAT_LEN, "<buffer=%d>", (int)buf->handle);
|
||||
ADD(buffers, CSTR_TO_OBJ(pattern_buflocal));
|
||||
});
|
||||
} else if (HAS_KEY(opts->buffer)) {
|
||||
} else if (HAS_KEY(opts, get_autocmds, buffer)) {
|
||||
VALIDATE_EXP(false, "buffer", "Integer or Array", api_typename(opts->buffer.type), {
|
||||
goto cleanup;
|
||||
});
|
||||
@ -408,12 +409,12 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VALIDATE((!HAS_KEY(opts->callback) || !HAS_KEY(opts->command)),
|
||||
VALIDATE((!HAS_KEY(opts, create_autocmd, callback) || !HAS_KEY(opts, create_autocmd, command)),
|
||||
"%s", "Cannot use both 'callback' and 'command'", {
|
||||
goto cleanup;
|
||||
});
|
||||
|
||||
if (HAS_KEY(opts->callback)) {
|
||||
if (HAS_KEY(opts, create_autocmd, callback)) {
|
||||
// NOTE: We could accept callable tables, but that isn't common in the API.
|
||||
|
||||
Object *callback = &opts->callback;
|
||||
@ -442,36 +443,33 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
|
||||
|
||||
aucmd.type = CALLABLE_CB;
|
||||
aucmd.callable.cb = cb;
|
||||
} else if (HAS_KEY(opts->command)) {
|
||||
Object *command = &opts->command;
|
||||
VALIDATE_T("command", kObjectTypeString, command->type, {
|
||||
goto cleanup;
|
||||
});
|
||||
} else if (HAS_KEY(opts, create_autocmd, command)) {
|
||||
aucmd.type = CALLABLE_EX;
|
||||
aucmd.callable.cmd = string_to_cstr(command->data.string);
|
||||
aucmd.callable.cmd = string_to_cstr(opts->command);
|
||||
} else {
|
||||
VALIDATE(false, "%s", "Required: 'command' or 'callback'", {
|
||||
goto cleanup;
|
||||
});
|
||||
}
|
||||
|
||||
bool is_once = api_object_to_bool(opts->once, "once", false, err);
|
||||
bool is_nested = api_object_to_bool(opts->nested, "nested", false, err);
|
||||
|
||||
int au_group = get_augroup_from_object(opts->group, err);
|
||||
if (au_group == AUGROUP_ERROR) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!get_patterns_from_pattern_or_buf(&patterns, opts->pattern, opts->buffer, err)) {
|
||||
bool has_buffer = HAS_KEY(opts, create_autocmd, buffer);
|
||||
|
||||
VALIDATE((!HAS_KEY(opts, create_autocmd, pattern) || !has_buffer),
|
||||
"%s", "Cannot use both 'pattern' and 'buffer' for the same autocmd", {
|
||||
goto cleanup;
|
||||
});
|
||||
|
||||
if (!get_patterns_from_pattern_or_buf(&patterns, opts->pattern, has_buffer, opts->buffer, err)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->desc)) {
|
||||
VALIDATE_T("desc", kObjectTypeString, opts->desc.type, {
|
||||
goto cleanup;
|
||||
});
|
||||
desc = opts->desc.data.string.data;
|
||||
if (HAS_KEY(opts, create_autocmd, desc)) {
|
||||
desc = opts->desc.data;
|
||||
}
|
||||
|
||||
if (patterns.size == 0) {
|
||||
@ -496,8 +494,8 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
|
||||
pat.data.string.data,
|
||||
(int)pat.data.string.size,
|
||||
au_group,
|
||||
is_once,
|
||||
is_nested,
|
||||
opts->once,
|
||||
opts->nested,
|
||||
desc,
|
||||
aucmd);
|
||||
});
|
||||
@ -568,7 +566,9 @@ void nvim_clear_autocmds(Dict(clear_autocmds) *opts, Error *err)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VALIDATE((!HAS_KEY(opts->pattern) || !HAS_KEY(opts->buffer)),
|
||||
bool has_buffer = HAS_KEY(opts, clear_autocmds, buffer);
|
||||
|
||||
VALIDATE((!HAS_KEY(opts, clear_autocmds, pattern) || !has_buffer),
|
||||
"%s", "Cannot use both 'pattern' and 'buffer'", {
|
||||
goto cleanup;
|
||||
});
|
||||
@ -578,7 +578,7 @@ void nvim_clear_autocmds(Dict(clear_autocmds) *opts, Error *err)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!get_patterns_from_pattern_or_buf(&patterns, opts->pattern, opts->buffer, err)) {
|
||||
if (!get_patterns_from_pattern_or_buf(&patterns, opts->pattern, has_buffer, opts->buffer, err)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -742,21 +742,22 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
|
||||
});
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->buffer)) {
|
||||
Object buf_obj = opts->buffer;
|
||||
VALIDATE_EXP((buf_obj.type == kObjectTypeInteger || buf_obj.type == kObjectTypeBuffer),
|
||||
"buffer", "Integer", api_typename(buf_obj.type), {
|
||||
bool has_buffer = false;
|
||||
if (HAS_KEY(opts, exec_autocmds, buffer)) {
|
||||
VALIDATE((!HAS_KEY(opts, exec_autocmds, pattern)),
|
||||
"%s", "Cannot use both 'pattern' and 'buffer' for the same autocmd", {
|
||||
goto cleanup;
|
||||
});
|
||||
|
||||
buf = find_buffer_by_handle((Buffer)buf_obj.data.integer, err);
|
||||
has_buffer = true;
|
||||
buf = find_buffer_by_handle(opts->buffer, err);
|
||||
|
||||
if (ERROR_SET(err)) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (!get_patterns_from_pattern_or_buf(&patterns, opts->pattern, opts->buffer, err)) {
|
||||
if (!get_patterns_from_pattern_or_buf(&patterns, opts->pattern, has_buffer, opts->buffer, err)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -764,20 +765,19 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
|
||||
ADD(patterns, STATIC_CSTR_TO_OBJ(""));
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->data)) {
|
||||
if (HAS_KEY(opts, exec_autocmds, data)) {
|
||||
data = &opts->data;
|
||||
}
|
||||
|
||||
modeline = api_object_to_bool(opts->modeline, "modeline", true, err);
|
||||
modeline = GET_BOOL_OR_TRUE(opts, exec_autocmds, modeline);
|
||||
|
||||
bool did_aucmd = false;
|
||||
FOREACH_ITEM(event_array, event_str, {
|
||||
GET_ONE_EVENT(event_nr, event_str, cleanup)
|
||||
|
||||
FOREACH_ITEM(patterns, pat, {
|
||||
char *fname = !HAS_KEY(opts->buffer) ? pat.data.string.data : NULL;
|
||||
did_aucmd |=
|
||||
apply_autocmds_group(event_nr, fname, NULL, true, au_group, buf, NULL, data);
|
||||
char *fname = !has_buffer ? pat.data.string.data : NULL;
|
||||
did_aucmd |= apply_autocmds_group(event_nr, fname, NULL, true, au_group, buf, NULL, data);
|
||||
})
|
||||
})
|
||||
|
||||
@ -837,17 +837,12 @@ static int get_augroup_from_object(Object group, Error *err)
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, Object buffer,
|
||||
Error *err)
|
||||
static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, bool has_buffer,
|
||||
Buffer buffer, Error *err)
|
||||
{
|
||||
const char pattern_buflocal[BUFLOCAL_PAT_LEN];
|
||||
|
||||
VALIDATE((!HAS_KEY(pattern) || !HAS_KEY(buffer)),
|
||||
"%s", "Cannot use both 'pattern' and 'buffer' for the same autocmd", {
|
||||
return false;
|
||||
});
|
||||
|
||||
if (HAS_KEY(pattern)) {
|
||||
if (pattern.type != kObjectTypeNil) {
|
||||
Object *v = &pattern;
|
||||
|
||||
if (v->type == kObjectTypeString) {
|
||||
@ -880,13 +875,8 @@ static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, Ob
|
||||
return false;
|
||||
});
|
||||
}
|
||||
} else if (HAS_KEY(buffer)) {
|
||||
VALIDATE_EXP((buffer.type == kObjectTypeInteger || buffer.type == kObjectTypeBuffer),
|
||||
"buffer", "Integer", api_typename(buffer.type), {
|
||||
return false;
|
||||
});
|
||||
|
||||
buf_T *buf = find_buffer_by_handle((Buffer)buffer.data.integer, err);
|
||||
} else if (has_buffer) {
|
||||
buf_T *buf = find_buffer_by_handle(buffer, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -341,16 +341,6 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define OBJ_TO_CMOD_FLAG(flag, value, default, varname) \
|
||||
do { \
|
||||
if (api_object_to_bool(value, varname, default, err)) { \
|
||||
cmdinfo.cmdmod.cmod_flags |= (flag); \
|
||||
} \
|
||||
if (ERROR_SET(err)) { \
|
||||
goto end; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VALIDATE_MOD(cond, mod_, name_) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
@ -359,18 +349,14 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
bool output;
|
||||
OBJ_TO_BOOL(output, opts->output, false, "'output'");
|
||||
|
||||
VALIDATE_R(HAS_KEY(cmd->cmd), "cmd", {
|
||||
VALIDATE_R(HAS_KEY(cmd, cmd, cmd), "cmd", {
|
||||
goto end;
|
||||
});
|
||||
VALIDATE_EXP((cmd->cmd.type == kObjectTypeString && cmd->cmd.data.string.data[0] != NUL),
|
||||
"cmd", "non-empty String", NULL, {
|
||||
VALIDATE_EXP((cmd->cmd.data[0] != NUL), "cmd", "non-empty String", NULL, {
|
||||
goto end;
|
||||
});
|
||||
|
||||
cmdname = string_to_cstr(cmd->cmd.data.string);
|
||||
cmdname = string_to_cstr(cmd->cmd);
|
||||
ea.cmd = cmdname;
|
||||
|
||||
char *p = find_ex_command(&ea, NULL);
|
||||
@ -407,15 +393,11 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
|
||||
}
|
||||
|
||||
// Parse command arguments since it's needed to get the command address type.
|
||||
if (HAS_KEY(cmd->args)) {
|
||||
VALIDATE_T("args", kObjectTypeArray, cmd->args.type, {
|
||||
goto end;
|
||||
});
|
||||
|
||||
if (HAS_KEY(cmd, cmd, args)) {
|
||||
// Process all arguments. Convert non-String arguments to String and check if String arguments
|
||||
// have non-whitespace characters.
|
||||
for (size_t i = 0; i < cmd->args.data.array.size; i++) {
|
||||
Object elem = cmd->args.data.array.items[i];
|
||||
for (size_t i = 0; i < cmd->args.size; i++) {
|
||||
Object elem = cmd->args.items[i];
|
||||
char *data_str;
|
||||
|
||||
switch (elem.type) {
|
||||
@ -477,16 +459,13 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
|
||||
// since it only ever checks the first argument.
|
||||
set_cmd_addr_type(&ea, args.size > 0 ? args.items[0].data.string.data : NULL);
|
||||
|
||||
if (HAS_KEY(cmd->range)) {
|
||||
VALIDATE_MOD((ea.argt & EX_RANGE), "range", cmd->cmd.data.string.data);
|
||||
VALIDATE_T("range", kObjectTypeArray, cmd->range.type, {
|
||||
goto end;
|
||||
});
|
||||
VALIDATE_EXP((cmd->range.data.array.size <= 2), "range", "<=2 elements", NULL, {
|
||||
if (HAS_KEY(cmd, cmd, range)) {
|
||||
VALIDATE_MOD((ea.argt & EX_RANGE), "range", cmd->cmd.data);
|
||||
VALIDATE_EXP((cmd->range.size <= 2), "range", "<=2 elements", NULL, {
|
||||
goto end;
|
||||
});
|
||||
|
||||
Array range = cmd->range.data.array;
|
||||
Array range = cmd->range;
|
||||
ea.addr_count = (int)range.size;
|
||||
|
||||
for (size_t i = 0; i < range.size; i++) {
|
||||
@ -519,22 +498,21 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
|
||||
}
|
||||
}
|
||||
|
||||
if (HAS_KEY(cmd->count)) {
|
||||
VALIDATE_MOD((ea.argt & EX_COUNT), "count", cmd->cmd.data.string.data);
|
||||
VALIDATE_EXP((cmd->count.type == kObjectTypeInteger && cmd->count.data.integer >= 0),
|
||||
"count", "non-negative Integer", NULL, {
|
||||
if (HAS_KEY(cmd, cmd, count)) {
|
||||
VALIDATE_MOD((ea.argt & EX_COUNT), "count", cmd->cmd.data);
|
||||
VALIDATE_EXP((cmd->count >= 0), "count", "non-negative Integer", NULL, {
|
||||
goto end;
|
||||
});
|
||||
set_cmd_count(&ea, (linenr_T)cmd->count.data.integer, true);
|
||||
set_cmd_count(&ea, (linenr_T)cmd->count, true);
|
||||
}
|
||||
|
||||
if (HAS_KEY(cmd->reg)) {
|
||||
VALIDATE_MOD((ea.argt & EX_REGSTR), "register", cmd->cmd.data.string.data);
|
||||
VALIDATE_EXP((cmd->reg.type == kObjectTypeString && cmd->reg.data.string.size == 1),
|
||||
"reg", "single character", cmd->reg.data.string.data, {
|
||||
if (HAS_KEY(cmd, cmd, reg)) {
|
||||
VALIDATE_MOD((ea.argt & EX_REGSTR), "register", cmd->cmd.data);
|
||||
VALIDATE_EXP((cmd->reg.size == 1),
|
||||
"reg", "single character", cmd->reg.data, {
|
||||
goto end;
|
||||
});
|
||||
char regname = cmd->reg.data.string.data[0];
|
||||
char regname = cmd->reg.data[0];
|
||||
VALIDATE((regname != '='), "%s", "Cannot use register \"=", {
|
||||
goto end;
|
||||
});
|
||||
@ -545,22 +523,17 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
|
||||
ea.regname = (uint8_t)regname;
|
||||
}
|
||||
|
||||
OBJ_TO_BOOL(ea.forceit, cmd->bang, false, "'bang'");
|
||||
VALIDATE_MOD((!ea.forceit || (ea.argt & EX_BANG)), "bang", cmd->cmd.data.string.data);
|
||||
ea.forceit = cmd->bang;
|
||||
VALIDATE_MOD((!ea.forceit || (ea.argt & EX_BANG)), "bang", cmd->cmd.data);
|
||||
|
||||
if (HAS_KEY(cmd->magic)) {
|
||||
VALIDATE_T_DICT("magic", cmd->magic, {
|
||||
goto end;
|
||||
});
|
||||
|
||||
Dict(cmd_magic) magic = { 0 };
|
||||
if (!api_dict_to_keydict(&magic, KeyDict_cmd_magic_get_field,
|
||||
cmd->magic.data.dictionary, err)) {
|
||||
if (HAS_KEY(cmd, cmd, magic)) {
|
||||
Dict(cmd_magic) magic[1] = { 0 };
|
||||
if (!api_dict_to_keydict(magic, KeyDict_cmd_magic_get_field, cmd->magic, err)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
OBJ_TO_BOOL(cmdinfo.magic.file, magic.file, ea.argt & EX_XFILE, "'magic.file'");
|
||||
OBJ_TO_BOOL(cmdinfo.magic.bar, magic.bar, ea.argt & EX_TRLBAR, "'magic.bar'");
|
||||
cmdinfo.magic.file = HAS_KEY(magic, cmd_magic, file) ? magic->file : (ea.argt & EX_XFILE);
|
||||
cmdinfo.magic.bar = HAS_KEY(magic, cmd_magic, bar) ? magic->bar : (ea.argt & EX_TRLBAR);
|
||||
if (cmdinfo.magic.file) {
|
||||
ea.argt |= EX_XFILE;
|
||||
} else {
|
||||
@ -571,89 +544,63 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
|
||||
cmdinfo.magic.bar = ea.argt & EX_TRLBAR;
|
||||
}
|
||||
|
||||
if (HAS_KEY(cmd->mods)) {
|
||||
VALIDATE_T_DICT("mods", cmd->mods, {
|
||||
goto end;
|
||||
});
|
||||
|
||||
Dict(cmd_mods) mods = { 0 };
|
||||
if (!api_dict_to_keydict(&mods, KeyDict_cmd_mods_get_field, cmd->mods.data.dictionary, err)) {
|
||||
if (HAS_KEY(cmd, cmd, mods)) {
|
||||
Dict(cmd_mods) mods[1] = { 0 };
|
||||
if (!api_dict_to_keydict(mods, KeyDict_cmd_mods_get_field, cmd->mods, err)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (HAS_KEY(mods.filter)) {
|
||||
VALIDATE_T_DICT("mods.filter", mods.filter, {
|
||||
goto end;
|
||||
});
|
||||
|
||||
Dict(cmd_mods_filter) filter = { 0 };
|
||||
if (HAS_KEY(mods, cmd_mods, filter)) {
|
||||
Dict(cmd_mods_filter) filter[1] = { 0 };
|
||||
|
||||
if (!api_dict_to_keydict(&filter, KeyDict_cmd_mods_filter_get_field,
|
||||
mods.filter.data.dictionary, err)) {
|
||||
mods->filter, err)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (HAS_KEY(filter.pattern)) {
|
||||
VALIDATE_T2(filter.pattern, kObjectTypeString, {
|
||||
goto end;
|
||||
});
|
||||
|
||||
OBJ_TO_BOOL(cmdinfo.cmdmod.cmod_filter_force, filter.force, false, "'mods.filter.force'");
|
||||
if (HAS_KEY(filter, cmd_mods_filter, pattern)) {
|
||||
cmdinfo.cmdmod.cmod_filter_force = filter->force;
|
||||
|
||||
// "filter! // is not no-op, so add a filter if either the pattern is non-empty or if filter
|
||||
// is inverted.
|
||||
if (*filter.pattern.data.string.data != NUL || cmdinfo.cmdmod.cmod_filter_force) {
|
||||
cmdinfo.cmdmod.cmod_filter_pat = string_to_cstr(filter.pattern.data.string);
|
||||
if (*filter->pattern.data != NUL || cmdinfo.cmdmod.cmod_filter_force) {
|
||||
cmdinfo.cmdmod.cmod_filter_pat = string_to_cstr(filter->pattern);
|
||||
cmdinfo.cmdmod.cmod_filter_regmatch.regprog = vim_regcomp(cmdinfo.cmdmod.cmod_filter_pat,
|
||||
RE_MAGIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (HAS_KEY(mods.tab)) {
|
||||
VALIDATE_T2(mods.tab, kObjectTypeInteger, {
|
||||
goto end;
|
||||
});
|
||||
if ((int)mods.tab.data.integer >= 0) {
|
||||
if (HAS_KEY(mods, cmd_mods, tab)) {
|
||||
if ((int)mods->tab >= 0) {
|
||||
// Silently ignore negative integers to allow mods.tab to be set to -1.
|
||||
cmdinfo.cmdmod.cmod_tab = (int)mods.tab.data.integer + 1;
|
||||
cmdinfo.cmdmod.cmod_tab = (int)mods->tab + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (HAS_KEY(mods.verbose)) {
|
||||
VALIDATE_T2(mods.verbose, kObjectTypeInteger, {
|
||||
goto end;
|
||||
});
|
||||
if ((int)mods.verbose.data.integer >= 0) {
|
||||
if (HAS_KEY(mods, cmd_mods, verbose)) {
|
||||
if ((int)mods->verbose >= 0) {
|
||||
// Silently ignore negative integers to allow mods.verbose to be set to -1.
|
||||
cmdinfo.cmdmod.cmod_verbose = (int)mods.verbose.data.integer + 1;
|
||||
cmdinfo.cmdmod.cmod_verbose = (int)mods->verbose + 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool vertical;
|
||||
OBJ_TO_BOOL(vertical, mods.vertical, false, "'mods.vertical'");
|
||||
cmdinfo.cmdmod.cmod_split |= (vertical ? WSP_VERT : 0);
|
||||
cmdinfo.cmdmod.cmod_split |= (mods->vertical ? WSP_VERT : 0);
|
||||
|
||||
bool horizontal;
|
||||
OBJ_TO_BOOL(horizontal, mods.horizontal, false, "'mods.horizontal'");
|
||||
cmdinfo.cmdmod.cmod_split |= (horizontal ? WSP_HOR : 0);
|
||||
cmdinfo.cmdmod.cmod_split |= (mods->horizontal ? WSP_HOR : 0);
|
||||
|
||||
if (HAS_KEY(mods.split)) {
|
||||
VALIDATE_T2(mods.split, kObjectTypeString, {
|
||||
goto end;
|
||||
});
|
||||
|
||||
if (*mods.split.data.string.data == NUL) {
|
||||
if (HAS_KEY(mods, cmd_mods, split)) {
|
||||
if (*mods->split.data == NUL) {
|
||||
// Empty string, do nothing.
|
||||
} else if (strcmp(mods.split.data.string.data, "aboveleft") == 0
|
||||
|| strcmp(mods.split.data.string.data, "leftabove") == 0) {
|
||||
} else if (strcmp(mods->split.data, "aboveleft") == 0
|
||||
|| strcmp(mods->split.data, "leftabove") == 0) {
|
||||
cmdinfo.cmdmod.cmod_split |= WSP_ABOVE;
|
||||
} else if (strcmp(mods.split.data.string.data, "belowright") == 0
|
||||
|| strcmp(mods.split.data.string.data, "rightbelow") == 0) {
|
||||
} else if (strcmp(mods->split.data, "belowright") == 0
|
||||
|| strcmp(mods->split.data, "rightbelow") == 0) {
|
||||
cmdinfo.cmdmod.cmod_split |= WSP_BELOW;
|
||||
} else if (strcmp(mods.split.data.string.data, "topleft") == 0) {
|
||||
} else if (strcmp(mods->split.data, "topleft") == 0) {
|
||||
cmdinfo.cmdmod.cmod_split |= WSP_TOP;
|
||||
} else if (strcmp(mods.split.data.string.data, "botright") == 0) {
|
||||
} else if (strcmp(mods->split.data, "botright") == 0) {
|
||||
cmdinfo.cmdmod.cmod_split |= WSP_BOT;
|
||||
} else {
|
||||
VALIDATE_S(false, "mods.split", "", {
|
||||
@ -662,20 +609,25 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
|
||||
}
|
||||
}
|
||||
|
||||
OBJ_TO_CMOD_FLAG(CMOD_SILENT, mods.silent, false, "'mods.silent'");
|
||||
OBJ_TO_CMOD_FLAG(CMOD_ERRSILENT, mods.emsg_silent, false, "'mods.emsg_silent'");
|
||||
OBJ_TO_CMOD_FLAG(CMOD_UNSILENT, mods.unsilent, false, "'mods.unsilent'");
|
||||
OBJ_TO_CMOD_FLAG(CMOD_SANDBOX, mods.sandbox, false, "'mods.sandbox'");
|
||||
OBJ_TO_CMOD_FLAG(CMOD_NOAUTOCMD, mods.noautocmd, false, "'mods.noautocmd'");
|
||||
OBJ_TO_CMOD_FLAG(CMOD_BROWSE, mods.browse, false, "'mods.browse'");
|
||||
OBJ_TO_CMOD_FLAG(CMOD_CONFIRM, mods.confirm, false, "'mods.confirm'");
|
||||
OBJ_TO_CMOD_FLAG(CMOD_HIDE, mods.hide, false, "'mods.hide'");
|
||||
OBJ_TO_CMOD_FLAG(CMOD_KEEPALT, mods.keepalt, false, "'mods.keepalt'");
|
||||
OBJ_TO_CMOD_FLAG(CMOD_KEEPJUMPS, mods.keepjumps, false, "'mods.keepjumps'");
|
||||
OBJ_TO_CMOD_FLAG(CMOD_KEEPMARKS, mods.keepmarks, false, "'mods.keepmarks'");
|
||||
OBJ_TO_CMOD_FLAG(CMOD_KEEPPATTERNS, mods.keeppatterns, false, "'mods.keeppatterns'");
|
||||
OBJ_TO_CMOD_FLAG(CMOD_LOCKMARKS, mods.lockmarks, false, "'mods.lockmarks'");
|
||||
OBJ_TO_CMOD_FLAG(CMOD_NOSWAPFILE, mods.noswapfile, false, "'mods.noswapfile'");
|
||||
#define OBJ_TO_CMOD_FLAG(flag, value) \
|
||||
if (value) { \
|
||||
cmdinfo.cmdmod.cmod_flags |= (flag); \
|
||||
}
|
||||
|
||||
OBJ_TO_CMOD_FLAG(CMOD_SILENT, mods->silent);
|
||||
OBJ_TO_CMOD_FLAG(CMOD_ERRSILENT, mods->emsg_silent);
|
||||
OBJ_TO_CMOD_FLAG(CMOD_UNSILENT, mods->unsilent);
|
||||
OBJ_TO_CMOD_FLAG(CMOD_SANDBOX, mods->sandbox);
|
||||
OBJ_TO_CMOD_FLAG(CMOD_NOAUTOCMD, mods->noautocmd);
|
||||
OBJ_TO_CMOD_FLAG(CMOD_BROWSE, mods->browse);
|
||||
OBJ_TO_CMOD_FLAG(CMOD_CONFIRM, mods->confirm);
|
||||
OBJ_TO_CMOD_FLAG(CMOD_HIDE, mods->hide);
|
||||
OBJ_TO_CMOD_FLAG(CMOD_KEEPALT, mods->keepalt);
|
||||
OBJ_TO_CMOD_FLAG(CMOD_KEEPJUMPS, mods->keepjumps);
|
||||
OBJ_TO_CMOD_FLAG(CMOD_KEEPMARKS, mods->keepmarks);
|
||||
OBJ_TO_CMOD_FLAG(CMOD_KEEPPATTERNS, mods->keeppatterns);
|
||||
OBJ_TO_CMOD_FLAG(CMOD_LOCKMARKS, mods->lockmarks);
|
||||
OBJ_TO_CMOD_FLAG(CMOD_NOSWAPFILE, mods->noswapfile);
|
||||
|
||||
if (cmdinfo.cmdmod.cmod_flags & CMOD_ERRSILENT) {
|
||||
// CMOD_ERRSILENT must imply CMOD_SILENT, otherwise apply_cmdmod() and undo_cmdmod() won't
|
||||
@ -699,13 +651,13 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
|
||||
garray_T * const save_capture_ga = capture_ga;
|
||||
const int save_msg_col = msg_col;
|
||||
|
||||
if (output) {
|
||||
if (opts->output) {
|
||||
ga_init(&capture_local, 1, 80);
|
||||
capture_ga = &capture_local;
|
||||
}
|
||||
|
||||
TRY_WRAP(err, {
|
||||
if (output) {
|
||||
if (opts->output) {
|
||||
msg_silent++;
|
||||
msg_col = 0; // prevent leading spaces
|
||||
}
|
||||
@ -714,7 +666,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
|
||||
execute_cmd(&ea, &cmdinfo, false);
|
||||
});
|
||||
|
||||
if (output) {
|
||||
if (opts->output) {
|
||||
capture_ga = save_capture_ga;
|
||||
msg_silent = save_msg_silent;
|
||||
// Put msg_col back where it was, since nothing should have been written.
|
||||
@ -726,7 +678,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
|
||||
goto clear_ga;
|
||||
}
|
||||
|
||||
if (output && capture_local.ga_len > 1) {
|
||||
if (opts->output && capture_local.ga_len > 1) {
|
||||
retv = (String){
|
||||
.data = capture_local.ga_data,
|
||||
.size = (size_t)capture_local.ga_len,
|
||||
@ -740,7 +692,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
|
||||
goto end;
|
||||
}
|
||||
clear_ga:
|
||||
if (output) {
|
||||
if (opts->output) {
|
||||
ga_clear(&capture_local);
|
||||
}
|
||||
end:
|
||||
@ -1037,7 +989,7 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
|
||||
name.data, {
|
||||
goto err;
|
||||
});
|
||||
VALIDATE((!HAS_KEY(opts->range) || !HAS_KEY(opts->count)), "%s",
|
||||
VALIDATE((!HAS_KEY(opts, user_command, range) || !HAS_KEY(opts, user_command, count)), "%s",
|
||||
"Cannot use both 'range' and 'count'", {
|
||||
goto err;
|
||||
});
|
||||
@ -1075,13 +1027,14 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
|
||||
goto err;
|
||||
});
|
||||
}
|
||||
} else if (HAS_KEY(opts->nargs)) {
|
||||
} else if (HAS_KEY(opts, user_command, nargs)) {
|
||||
VALIDATE_S(false, "nargs", "", {
|
||||
goto err;
|
||||
});
|
||||
}
|
||||
|
||||
VALIDATE((!HAS_KEY(opts->complete) || argt), "%s", "'complete' used without 'nargs'", {
|
||||
VALIDATE((!HAS_KEY(opts, user_command, complete) || argt),
|
||||
"%s", "'complete' used without 'nargs'", {
|
||||
goto err;
|
||||
});
|
||||
|
||||
@ -1101,7 +1054,7 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
|
||||
argt |= EX_RANGE | EX_ZEROR;
|
||||
def = opts->range.data.integer;
|
||||
addr_type_arg = ADDR_LINES;
|
||||
} else if (HAS_KEY(opts->range)) {
|
||||
} else if (HAS_KEY(opts, user_command, range)) {
|
||||
VALIDATE_S(false, "range", "", {
|
||||
goto err;
|
||||
});
|
||||
@ -1117,13 +1070,13 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
|
||||
argt |= EX_COUNT | EX_ZEROR | EX_RANGE;
|
||||
addr_type_arg = ADDR_OTHER;
|
||||
def = opts->count.data.integer;
|
||||
} else if (HAS_KEY(opts->count)) {
|
||||
} else if (HAS_KEY(opts, user_command, count)) {
|
||||
VALIDATE_S(false, "count", "", {
|
||||
goto err;
|
||||
});
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->addr)) {
|
||||
if (HAS_KEY(opts, user_command, addr)) {
|
||||
VALIDATE_T("addr", kObjectTypeString, opts->addr.type, {
|
||||
goto err;
|
||||
});
|
||||
@ -1139,31 +1092,23 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
|
||||
}
|
||||
}
|
||||
|
||||
if (api_object_to_bool(opts->bang, "bang", false, err)) {
|
||||
if (opts->bang) {
|
||||
argt |= EX_BANG;
|
||||
} else if (ERROR_SET(err)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (api_object_to_bool(opts->bar, "bar", false, err)) {
|
||||
if (opts->bar) {
|
||||
argt |= EX_TRLBAR;
|
||||
} else if (ERROR_SET(err)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (api_object_to_bool(opts->register_, "register", false, err)) {
|
||||
if (opts->register_) {
|
||||
argt |= EX_REGSTR;
|
||||
} else if (ERROR_SET(err)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (api_object_to_bool(opts->keepscript, "keepscript", false, err)) {
|
||||
if (opts->keepscript) {
|
||||
argt |= EX_KEEPSCRIPT;
|
||||
} else if (ERROR_SET(err)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
bool force = api_object_to_bool(opts->force, "force", true, err);
|
||||
bool force = GET_BOOL_OR_TRUE(opts, user_command, force);
|
||||
if (ERROR_SET(err)) {
|
||||
goto err;
|
||||
}
|
||||
@ -1178,13 +1123,13 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
|
||||
"complete", opts->complete.data.string.data, {
|
||||
goto err;
|
||||
});
|
||||
} else if (HAS_KEY(opts->complete)) {
|
||||
} else if (HAS_KEY(opts, user_command, complete)) {
|
||||
VALIDATE_EXP(false, "complete", "Function or String", NULL, {
|
||||
goto err;
|
||||
});
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->preview)) {
|
||||
if (HAS_KEY(opts, user_command, preview)) {
|
||||
VALIDATE_T("preview", kObjectTypeLuaRef, opts->preview.type, {
|
||||
goto err;
|
||||
});
|
||||
@ -1254,13 +1199,12 @@ Dictionary nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Error
|
||||
FUNC_API_SINCE(4)
|
||||
{
|
||||
bool global = (buffer == -1);
|
||||
bool builtin = api_object_to_bool(opts->builtin, "builtin", false, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return (Dictionary)ARRAY_DICT_INIT;
|
||||
}
|
||||
|
||||
if (global) {
|
||||
if (builtin) {
|
||||
if (opts->builtin) {
|
||||
api_set_error(err, kErrorTypeValidation, "builtin=true not implemented");
|
||||
return (Dictionary)ARRAY_DICT_INIT;
|
||||
}
|
||||
@ -1268,7 +1212,7 @@ Dictionary nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Error
|
||||
}
|
||||
|
||||
buf_T *buf = find_buffer_by_handle(buffer, err);
|
||||
if (builtin || !buf) {
|
||||
if (opts->builtin || !buf) {
|
||||
return (Dictionary)ARRAY_DICT_INIT;
|
||||
}
|
||||
return commands_array(buf);
|
||||
|
@ -35,8 +35,7 @@ String nvim_exec(uint64_t channel_id, String src, Boolean output, Error *err)
|
||||
FUNC_API_SINCE(7)
|
||||
FUNC_API_DEPRECATED_SINCE(11)
|
||||
{
|
||||
Dict(exec_opts) opts = { 0 };
|
||||
opts.output = BOOLEAN_OBJ(output);
|
||||
Dict(exec_opts) opts = { .output = output };
|
||||
return exec_impl(channel_id, src, &opts, err);
|
||||
}
|
||||
|
||||
@ -46,8 +45,7 @@ String nvim_command_output(uint64_t channel_id, String command, Error *err)
|
||||
FUNC_API_SINCE(1)
|
||||
FUNC_API_DEPRECATED_SINCE(7)
|
||||
{
|
||||
Dict(exec_opts) opts = { 0 };
|
||||
opts.output = BOOLEAN_OBJ(true);
|
||||
Dict(exec_opts) opts = { .output = true };
|
||||
return exec_impl(channel_id, command, &opts, err);
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "lauxlib.h"
|
||||
#include "nvim/api/extmark.h"
|
||||
#include "nvim/api/private/defs.h"
|
||||
#include "nvim/api/private/dispatch.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/api/private/validate.h"
|
||||
#include "nvim/buffer_defs.h"
|
||||
@ -581,40 +582,32 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
});
|
||||
|
||||
uint32_t id = 0;
|
||||
if (HAS_KEY(opts->id)) {
|
||||
VALIDATE_EXP((opts->id.type == kObjectTypeInteger && opts->id.data.integer > 0),
|
||||
"id", "positive Integer", NULL, {
|
||||
if (HAS_KEY(opts, set_extmark, id)) {
|
||||
VALIDATE_EXP((opts->id > 0), "id", "positive Integer", NULL, {
|
||||
goto error;
|
||||
});
|
||||
|
||||
id = (uint32_t)opts->id.data.integer;
|
||||
id = (uint32_t)opts->id;
|
||||
}
|
||||
|
||||
int line2 = -1;
|
||||
bool did_end_line = false;
|
||||
|
||||
// For backward compatibility we support "end_line" as an alias for "end_row"
|
||||
if (HAS_KEY(opts->end_line)) {
|
||||
VALIDATE(!HAS_KEY(opts->end_row), "%s", "cannot use both 'end_row' and 'end_line'", {
|
||||
if (HAS_KEY(opts, set_extmark, end_line)) {
|
||||
VALIDATE(!HAS_KEY(opts, set_extmark, end_row),
|
||||
"%s", "cannot use both 'end_row' and 'end_line'", {
|
||||
goto error;
|
||||
});
|
||||
|
||||
opts->end_row = opts->end_line;
|
||||
did_end_line = true;
|
||||
}
|
||||
|
||||
#define OPTION_TO_BOOL(target, name, val) \
|
||||
target = api_object_to_bool(opts->name, #name, val, err); \
|
||||
if (ERROR_SET(err)) { \
|
||||
goto error; \
|
||||
}
|
||||
bool strict = GET_BOOL_OR_TRUE(opts, set_extmark, strict);
|
||||
|
||||
bool strict = true;
|
||||
OPTION_TO_BOOL(strict, strict, true);
|
||||
|
||||
if (HAS_KEY(opts->end_row)) {
|
||||
VALIDATE_T("end_row", kObjectTypeInteger, opts->end_row.type, {
|
||||
goto error;
|
||||
});
|
||||
|
||||
Integer val = opts->end_row.data.integer;
|
||||
if (HAS_KEY(opts, set_extmark, end_row) || did_end_line) {
|
||||
Integer val = opts->end_row;
|
||||
VALIDATE_RANGE((val >= 0 && !(val > buf->b_ml.ml_line_count && strict)), "end_row", {
|
||||
goto error;
|
||||
});
|
||||
@ -622,12 +615,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
}
|
||||
|
||||
colnr_T col2 = -1;
|
||||
if (HAS_KEY(opts->end_col)) {
|
||||
VALIDATE_T("end_col", kObjectTypeInteger, opts->end_col.type, {
|
||||
goto error;
|
||||
});
|
||||
|
||||
Integer val = opts->end_col.data.integer;
|
||||
if (HAS_KEY(opts, set_extmark, end_col)) {
|
||||
Integer val = opts->end_col;
|
||||
VALIDATE_RANGE((val >= 0 && val <= MAXCOL), "end_col", {
|
||||
goto error;
|
||||
});
|
||||
@ -636,6 +625,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
|
||||
// uncrustify:off
|
||||
|
||||
// TODO(bfredl): keyset type alias for hl_group? (nil|int|string)
|
||||
struct {
|
||||
const char *name;
|
||||
Object *opt;
|
||||
@ -652,7 +642,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
// uncrustify:on
|
||||
|
||||
for (int j = 0; hls[j].name && hls[j].dest; j++) {
|
||||
if (HAS_KEY(*hls[j].opt)) {
|
||||
if (hls[j].opt->type != kObjectTypeNil) {
|
||||
*hls[j].dest = object_to_hl_id(*hls[j].opt, hls[j].name, err);
|
||||
if (ERROR_SET(err)) {
|
||||
goto error;
|
||||
@ -661,12 +651,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
}
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->conceal)) {
|
||||
VALIDATE_T("conceal", kObjectTypeString, opts->conceal.type, {
|
||||
goto error;
|
||||
});
|
||||
|
||||
String c = opts->conceal.data.string;
|
||||
if (HAS_KEY(opts, set_extmark, conceal)) {
|
||||
String c = opts->conceal;
|
||||
decor.conceal = true;
|
||||
if (c.size) {
|
||||
decor.conceal_char = utf_ptr2char(c.data);
|
||||
@ -674,25 +660,16 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
has_decor = true;
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->virt_text)) {
|
||||
VALIDATE_T("virt_text", kObjectTypeArray, opts->virt_text.type, {
|
||||
goto error;
|
||||
});
|
||||
|
||||
decor.virt_text = parse_virt_text(opts->virt_text.data.array, err,
|
||||
&decor.virt_text_width);
|
||||
if (HAS_KEY(opts, set_extmark, virt_text)) {
|
||||
decor.virt_text = parse_virt_text(opts->virt_text, err, &decor.virt_text_width);
|
||||
has_decor = true;
|
||||
if (ERROR_SET(err)) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->virt_text_pos)) {
|
||||
VALIDATE_T("virt_text_pos", kObjectTypeString, opts->virt_text_pos.type, {
|
||||
goto error;
|
||||
});
|
||||
|
||||
String str = opts->virt_text_pos.data.string;
|
||||
if (HAS_KEY(opts, set_extmark, virt_text_pos)) {
|
||||
String str = opts->virt_text_pos;
|
||||
if (strequal("eol", str.data)) {
|
||||
decor.virt_text_pos = kVTEndOfLine;
|
||||
} else if (strequal("overlay", str.data)) {
|
||||
@ -708,24 +685,16 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
}
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->virt_text_win_col)) {
|
||||
VALIDATE_T("virt_text_win_col", kObjectTypeInteger, opts->virt_text_win_col.type, {
|
||||
goto error;
|
||||
});
|
||||
|
||||
decor.col = (int)opts->virt_text_win_col.data.integer;
|
||||
if (HAS_KEY(opts, set_extmark, virt_text_win_col)) {
|
||||
decor.col = (int)opts->virt_text_win_col;
|
||||
decor.virt_text_pos = kVTWinCol;
|
||||
}
|
||||
|
||||
OPTION_TO_BOOL(decor.virt_text_hide, virt_text_hide, false);
|
||||
OPTION_TO_BOOL(decor.hl_eol, hl_eol, false);
|
||||
decor.hl_eol = opts->hl_eol;
|
||||
decor.virt_text_hide = opts->virt_text_hide;
|
||||
|
||||
if (HAS_KEY(opts->hl_mode)) {
|
||||
VALIDATE_T("hl_mode", kObjectTypeString, opts->hl_mode.type, {
|
||||
goto error;
|
||||
});
|
||||
|
||||
String str = opts->hl_mode.data.string;
|
||||
if (HAS_KEY(opts, set_extmark, hl_mode)) {
|
||||
String str = opts->hl_mode;
|
||||
if (strequal("replace", str.data)) {
|
||||
decor.hl_mode = kHlModeReplace;
|
||||
} else if (strequal("combine", str.data)) {
|
||||
@ -744,15 +713,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
}
|
||||
}
|
||||
|
||||
bool virt_lines_leftcol = false;
|
||||
OPTION_TO_BOOL(virt_lines_leftcol, virt_lines_leftcol, false);
|
||||
bool virt_lines_leftcol = opts->virt_lines_leftcol;
|
||||
|
||||
if (HAS_KEY(opts->virt_lines)) {
|
||||
VALIDATE_T("virt_lines", kObjectTypeArray, opts->virt_lines.type, {
|
||||
goto error;
|
||||
});
|
||||
|
||||
Array a = opts->virt_lines.data.array;
|
||||
if (HAS_KEY(opts, set_extmark, virt_lines)) {
|
||||
Array a = opts->virt_lines;
|
||||
for (size_t j = 0; j < a.size; j++) {
|
||||
VALIDATE_T("virt_text_line", kObjectTypeArray, a.items[j].type, {
|
||||
goto error;
|
||||
@ -767,61 +731,44 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
}
|
||||
}
|
||||
|
||||
OPTION_TO_BOOL(decor.virt_lines_above, virt_lines_above, false);
|
||||
decor.virt_lines_above = opts->virt_lines_above;
|
||||
|
||||
if (HAS_KEY(opts->priority)) {
|
||||
VALIDATE_T("priority", kObjectTypeInteger, opts->priority.type, {
|
||||
if (HAS_KEY(opts, set_extmark, priority)) {
|
||||
VALIDATE_RANGE((opts->priority >= 0 && opts->priority <= UINT16_MAX), "priority", {
|
||||
goto error;
|
||||
});
|
||||
|
||||
Integer val = opts->priority.data.integer;
|
||||
|
||||
VALIDATE_RANGE((val >= 0 && val <= UINT16_MAX), "priority", {
|
||||
goto error;
|
||||
});
|
||||
decor.priority = (DecorPriority)val;
|
||||
decor.priority = (DecorPriority)opts->priority;
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->sign_text)) {
|
||||
VALIDATE_T("sign_text", kObjectTypeString, opts->sign_text.type, {
|
||||
goto error;
|
||||
});
|
||||
|
||||
VALIDATE_S(init_sign_text(&decor.sign_text, opts->sign_text.data.string.data),
|
||||
if (HAS_KEY(opts, set_extmark, sign_text)) {
|
||||
VALIDATE_S(init_sign_text(&decor.sign_text, opts->sign_text.data),
|
||||
"sign_text", "", {
|
||||
goto error;
|
||||
});
|
||||
has_decor = true;
|
||||
}
|
||||
|
||||
bool right_gravity = true;
|
||||
OPTION_TO_BOOL(right_gravity, right_gravity, true);
|
||||
bool right_gravity = GET_BOOL_OR_TRUE(opts, set_extmark, right_gravity);
|
||||
|
||||
// Only error out if they try to set end_right_gravity without
|
||||
// setting end_col or end_row
|
||||
VALIDATE(!(line2 == -1 && col2 == -1 && HAS_KEY(opts->end_right_gravity)),
|
||||
VALIDATE(!(line2 == -1 && col2 == -1 && HAS_KEY(opts, set_extmark, end_right_gravity)),
|
||||
"%s", "cannot set end_right_gravity without end_row or end_col", {
|
||||
goto error;
|
||||
});
|
||||
|
||||
bool end_right_gravity = false;
|
||||
OPTION_TO_BOOL(end_right_gravity, end_right_gravity, false);
|
||||
bool end_right_gravity = opts->end_right_gravity;
|
||||
|
||||
size_t len = 0;
|
||||
|
||||
bool ephemeral = false;
|
||||
OPTION_TO_BOOL(ephemeral, ephemeral, false);
|
||||
|
||||
if (!HAS_KEY(opts->spell)) {
|
||||
if (!HAS_KEY(opts, set_extmark, spell)) {
|
||||
decor.spell = kNone;
|
||||
} else {
|
||||
bool spell = false;
|
||||
OPTION_TO_BOOL(spell, spell, false);
|
||||
decor.spell = spell ? kTrue : kFalse;
|
||||
decor.spell = opts->spell ? kTrue : kFalse;
|
||||
has_decor = true;
|
||||
}
|
||||
|
||||
OPTION_TO_BOOL(decor.ui_watched, ui_watched, false);
|
||||
decor.ui_watched = opts->ui_watched;
|
||||
if (decor.ui_watched) {
|
||||
has_decor = true;
|
||||
}
|
||||
@ -836,7 +783,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
});
|
||||
line = buf->b_ml.ml_line_count;
|
||||
} else if (line < buf->b_ml.ml_line_count) {
|
||||
len = ephemeral ? MAXCOL : strlen(ml_get_buf(buf, (linenr_T)line + 1, false));
|
||||
len = opts->ephemeral ? MAXCOL : strlen(ml_get_buf(buf, (linenr_T)line + 1, false));
|
||||
}
|
||||
|
||||
if (col == -1) {
|
||||
@ -854,7 +801,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
|
||||
if (col2 >= 0) {
|
||||
if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) {
|
||||
len = ephemeral ? MAXCOL : strlen(ml_get_buf(buf, (linenr_T)line2 + 1, false));
|
||||
len = opts->ephemeral ? MAXCOL : strlen(ml_get_buf(buf, (linenr_T)line2 + 1, false));
|
||||
} else if (line2 == buf->b_ml.ml_line_count) {
|
||||
// We are trying to add an extmark past final newline
|
||||
len = 0;
|
||||
@ -873,10 +820,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
}
|
||||
|
||||
// TODO(bfredl): synergize these two branches even more
|
||||
if (ephemeral && decor_state.win && decor_state.win->w_buffer == buf) {
|
||||
if (opts->ephemeral && decor_state.win && decor_state.win->w_buffer == buf) {
|
||||
decor_add_ephemeral((int)line, (int)col, line2, col2, &decor, (uint64_t)ns_id, id);
|
||||
} else {
|
||||
if (ephemeral) {
|
||||
if (opts->ephemeral) {
|
||||
api_set_error(err, kErrorTypeException, "not yet implemented");
|
||||
goto error;
|
||||
}
|
||||
@ -1107,7 +1054,7 @@ void nvim_set_decoration_provider(Integer ns_id, Dict(set_decoration_provider) *
|
||||
|
||||
struct {
|
||||
const char *name;
|
||||
Object *source;
|
||||
LuaRef *source;
|
||||
LuaRef *dest;
|
||||
} cbs[] = {
|
||||
{ "on_start", &opts->on_start, &p->redraw_start },
|
||||
@ -1121,25 +1068,18 @@ void nvim_set_decoration_provider(Integer ns_id, Dict(set_decoration_provider) *
|
||||
};
|
||||
|
||||
for (size_t i = 0; cbs[i].source && cbs[i].dest && cbs[i].name; i++) {
|
||||
Object *v = cbs[i].source;
|
||||
if (v->type == kObjectTypeNil) {
|
||||
LuaRef *v = cbs[i].source;
|
||||
if (*v <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
VALIDATE_T(cbs[i].name, kObjectTypeLuaRef, v->type, {
|
||||
goto error;
|
||||
});
|
||||
|
||||
*(cbs[i].dest) = v->data.luaref;
|
||||
v->data.luaref = LUA_NOREF;
|
||||
*(cbs[i].dest) = *v;
|
||||
*v = LUA_NOREF;
|
||||
}
|
||||
|
||||
p->active = true;
|
||||
p->hl_valid++;
|
||||
p->hl_cached = false;
|
||||
return;
|
||||
error:
|
||||
decor_provider_clear(p);
|
||||
}
|
||||
|
||||
/// Gets the line and column of an |extmark|.
|
||||
|
@ -4,135 +4,144 @@
|
||||
#include "nvim/api/private/defs.h"
|
||||
|
||||
typedef struct {
|
||||
Object types;
|
||||
OptionalKeys is_set__context_;
|
||||
Array types;
|
||||
} Dict(context);
|
||||
|
||||
typedef struct {
|
||||
Object on_start;
|
||||
Object on_buf;
|
||||
Object on_win;
|
||||
Object on_line;
|
||||
Object on_end;
|
||||
Object _on_hl_def;
|
||||
Object _on_spell_nav;
|
||||
OptionalKeys is_set__set_decoration_provider_;
|
||||
LuaRef on_start;
|
||||
LuaRef on_buf;
|
||||
LuaRef on_win;
|
||||
LuaRef on_line;
|
||||
LuaRef on_end;
|
||||
LuaRef _on_hl_def;
|
||||
LuaRef _on_spell_nav;
|
||||
} Dict(set_decoration_provider);
|
||||
|
||||
typedef struct {
|
||||
Object id;
|
||||
Object end_line;
|
||||
Object end_row;
|
||||
Object end_col;
|
||||
OptionalKeys is_set__set_extmark_;
|
||||
Integer id;
|
||||
Integer end_line;
|
||||
Integer end_row;
|
||||
Integer end_col;
|
||||
Object hl_group;
|
||||
Object virt_text;
|
||||
Object virt_text_pos;
|
||||
Object virt_text_win_col;
|
||||
Object virt_text_hide;
|
||||
Object hl_eol;
|
||||
Object hl_mode;
|
||||
Object ephemeral;
|
||||
Object priority;
|
||||
Object right_gravity;
|
||||
Object end_right_gravity;
|
||||
Object virt_lines;
|
||||
Object virt_lines_above;
|
||||
Object virt_lines_leftcol;
|
||||
Object strict;
|
||||
Object sign_text;
|
||||
Array virt_text;
|
||||
String virt_text_pos;
|
||||
Integer virt_text_win_col;
|
||||
Boolean virt_text_hide;
|
||||
Boolean hl_eol;
|
||||
String hl_mode;
|
||||
Boolean ephemeral;
|
||||
Integer priority;
|
||||
Boolean right_gravity;
|
||||
Boolean end_right_gravity;
|
||||
Array virt_lines;
|
||||
Boolean virt_lines_above;
|
||||
Boolean virt_lines_leftcol;
|
||||
Boolean strict;
|
||||
String sign_text;
|
||||
Object sign_hl_group;
|
||||
Object number_hl_group;
|
||||
Object line_hl_group;
|
||||
Object cursorline_hl_group;
|
||||
Object conceal;
|
||||
Object spell;
|
||||
Object ui_watched;
|
||||
String conceal;
|
||||
Boolean spell;
|
||||
Boolean ui_watched;
|
||||
} Dict(set_extmark);
|
||||
|
||||
typedef struct {
|
||||
Object noremap;
|
||||
Object nowait;
|
||||
Object silent;
|
||||
Object script;
|
||||
Object expr;
|
||||
Object unique;
|
||||
Object callback;
|
||||
Object desc;
|
||||
Object replace_keycodes;
|
||||
OptionalKeys is_set__keymap_;
|
||||
Boolean noremap;
|
||||
Boolean nowait;
|
||||
Boolean silent;
|
||||
Boolean script;
|
||||
Boolean expr;
|
||||
Boolean unique;
|
||||
LuaRef callback;
|
||||
String desc;
|
||||
Boolean replace_keycodes;
|
||||
} Dict(keymap);
|
||||
|
||||
typedef struct {
|
||||
Object builtin;
|
||||
Boolean builtin;
|
||||
} Dict(get_commands);
|
||||
|
||||
typedef struct {
|
||||
OptionalKeys is_set__user_command_;
|
||||
Object addr;
|
||||
Object bang;
|
||||
Object bar;
|
||||
Boolean bang;
|
||||
Boolean bar;
|
||||
Object complete;
|
||||
Object count;
|
||||
Object desc;
|
||||
Object force;
|
||||
Object keepscript;
|
||||
Boolean force;
|
||||
Boolean keepscript;
|
||||
Object nargs;
|
||||
Object preview;
|
||||
Object range;
|
||||
Object register_;
|
||||
Boolean register_;
|
||||
} Dict(user_command);
|
||||
|
||||
typedef struct {
|
||||
Object row;
|
||||
Object col;
|
||||
Object width;
|
||||
Object height;
|
||||
Object anchor;
|
||||
Object relative;
|
||||
Object win;
|
||||
Object bufpos;
|
||||
Object external;
|
||||
Object focusable;
|
||||
Object zindex;
|
||||
OptionalKeys is_set__float_config_;
|
||||
Float row;
|
||||
Float col;
|
||||
Integer width;
|
||||
Integer height;
|
||||
String anchor;
|
||||
String relative;
|
||||
Window win;
|
||||
Array bufpos;
|
||||
Boolean external;
|
||||
Boolean focusable;
|
||||
Integer zindex;
|
||||
Object border;
|
||||
Object title;
|
||||
Object title_pos;
|
||||
Object style;
|
||||
Object noautocmd;
|
||||
String title_pos;
|
||||
String style;
|
||||
Boolean noautocmd;
|
||||
} Dict(float_config);
|
||||
|
||||
typedef struct {
|
||||
Object is_lua;
|
||||
Object do_source;
|
||||
Boolean is_lua;
|
||||
Boolean do_source;
|
||||
} Dict(runtime);
|
||||
|
||||
typedef struct {
|
||||
Object winid;
|
||||
Object maxwidth;
|
||||
Object fillchar;
|
||||
Object highlights;
|
||||
Object use_winbar;
|
||||
Object use_tabline;
|
||||
Object use_statuscol_lnum;
|
||||
OptionalKeys is_set__eval_statusline_;
|
||||
Window winid;
|
||||
Integer maxwidth;
|
||||
String fillchar;
|
||||
Boolean highlights;
|
||||
Boolean use_winbar;
|
||||
Boolean use_tabline;
|
||||
Integer use_statuscol_lnum;
|
||||
} Dict(eval_statusline);
|
||||
|
||||
typedef struct {
|
||||
Object scope;
|
||||
Object win;
|
||||
Object buf;
|
||||
Object filetype;
|
||||
OptionalKeys is_set__option_;
|
||||
String scope;
|
||||
Window win;
|
||||
Buffer buf;
|
||||
String filetype;
|
||||
} Dict(option);
|
||||
|
||||
typedef struct {
|
||||
Object bold;
|
||||
Object standout;
|
||||
Object strikethrough;
|
||||
Object underline;
|
||||
Object undercurl;
|
||||
Object underdouble;
|
||||
Object underdotted;
|
||||
Object underdashed;
|
||||
Object italic;
|
||||
Object reverse;
|
||||
Object altfont;
|
||||
Object nocombine;
|
||||
Object default_;
|
||||
OptionalKeys is_set__highlight_;
|
||||
Boolean bold;
|
||||
Boolean standout;
|
||||
Boolean strikethrough;
|
||||
Boolean underline;
|
||||
Boolean undercurl;
|
||||
Boolean underdouble;
|
||||
Boolean underdotted;
|
||||
Boolean underdashed;
|
||||
Boolean italic;
|
||||
Boolean reverse;
|
||||
Boolean altfont;
|
||||
Boolean nocombine;
|
||||
Boolean default_;
|
||||
Object cterm;
|
||||
Object foreground;
|
||||
Object fg;
|
||||
@ -144,67 +153,73 @@ typedef struct {
|
||||
Object sp;
|
||||
Object link;
|
||||
Object global_link;
|
||||
Object fallback;
|
||||
Object blend;
|
||||
Object fg_indexed;
|
||||
Object bg_indexed;
|
||||
Boolean fallback;
|
||||
Integer blend;
|
||||
Boolean fg_indexed;
|
||||
Boolean bg_indexed;
|
||||
} Dict(highlight);
|
||||
|
||||
typedef struct {
|
||||
Object bold;
|
||||
Object standout;
|
||||
Object strikethrough;
|
||||
Object underline;
|
||||
Object undercurl;
|
||||
Object underdouble;
|
||||
Object underdotted;
|
||||
Object underdashed;
|
||||
Object italic;
|
||||
Object reverse;
|
||||
Object altfont;
|
||||
Object nocombine;
|
||||
Boolean bold;
|
||||
Boolean standout;
|
||||
Boolean strikethrough;
|
||||
Boolean underline;
|
||||
Boolean undercurl;
|
||||
Boolean underdouble;
|
||||
Boolean underdotted;
|
||||
Boolean underdashed;
|
||||
Boolean italic;
|
||||
Boolean reverse;
|
||||
Boolean altfont;
|
||||
Boolean nocombine;
|
||||
} Dict(highlight_cterm);
|
||||
|
||||
typedef struct {
|
||||
Object id;
|
||||
Object name;
|
||||
Object link;
|
||||
OptionalKeys is_set__get_highlight_;
|
||||
Integer id;
|
||||
String name;
|
||||
Boolean link;
|
||||
} Dict(get_highlight);
|
||||
|
||||
typedef struct {
|
||||
Object start_row;
|
||||
Object end_row;
|
||||
Object start_vcol;
|
||||
Object end_vcol;
|
||||
OptionalKeys is_set__win_text_height_;
|
||||
Integer start_row;
|
||||
Integer end_row;
|
||||
Integer start_vcol;
|
||||
Integer end_vcol;
|
||||
} Dict(win_text_height);
|
||||
|
||||
typedef struct {
|
||||
Object buffer;
|
||||
OptionalKeys is_set__clear_autocmds_;
|
||||
Buffer buffer;
|
||||
Object event;
|
||||
Object group;
|
||||
Object pattern;
|
||||
} Dict(clear_autocmds);
|
||||
|
||||
typedef struct {
|
||||
Object buffer;
|
||||
OptionalKeys is_set__create_autocmd_;
|
||||
Buffer buffer;
|
||||
Object callback;
|
||||
Object command;
|
||||
Object desc;
|
||||
String command;
|
||||
String desc;
|
||||
Object group;
|
||||
Object nested;
|
||||
Object once;
|
||||
Boolean nested;
|
||||
Boolean once;
|
||||
Object pattern;
|
||||
} Dict(create_autocmd);
|
||||
|
||||
typedef struct {
|
||||
Object buffer;
|
||||
OptionalKeys is_set__exec_autocmds_;
|
||||
Buffer buffer;
|
||||
Object group;
|
||||
Object modeline;
|
||||
Boolean modeline;
|
||||
Object pattern;
|
||||
Object data;
|
||||
} Dict(exec_autocmds);
|
||||
|
||||
typedef struct {
|
||||
OptionalKeys is_set__get_autocmds_;
|
||||
Object event;
|
||||
Object group;
|
||||
Object pattern;
|
||||
@ -216,62 +231,66 @@ typedef struct {
|
||||
} Dict(create_augroup);
|
||||
|
||||
typedef struct {
|
||||
Object cmd;
|
||||
Object range;
|
||||
Object count;
|
||||
Object reg;
|
||||
Object bang;
|
||||
Object args;
|
||||
Object magic;
|
||||
Object mods;
|
||||
OptionalKeys is_set__cmd_;
|
||||
String cmd;
|
||||
Array range;
|
||||
Integer count;
|
||||
String reg;
|
||||
Boolean bang;
|
||||
Array args;
|
||||
Dictionary magic;
|
||||
Dictionary mods;
|
||||
Object nargs;
|
||||
Object addr;
|
||||
Object nextcmd;
|
||||
} Dict(cmd);
|
||||
|
||||
typedef struct {
|
||||
Object file;
|
||||
Object bar;
|
||||
OptionalKeys is_set__cmd_magic_;
|
||||
Boolean file;
|
||||
Boolean bar;
|
||||
} Dict(cmd_magic);
|
||||
|
||||
typedef struct {
|
||||
Object silent;
|
||||
Object emsg_silent;
|
||||
Object unsilent;
|
||||
Object filter;
|
||||
Object sandbox;
|
||||
Object noautocmd;
|
||||
Object browse;
|
||||
Object confirm;
|
||||
Object hide;
|
||||
Object horizontal;
|
||||
Object keepalt;
|
||||
Object keepjumps;
|
||||
Object keepmarks;
|
||||
Object keeppatterns;
|
||||
Object lockmarks;
|
||||
Object noswapfile;
|
||||
Object tab;
|
||||
Object verbose;
|
||||
Object vertical;
|
||||
Object split;
|
||||
OptionalKeys is_set__cmd_mods_;
|
||||
Boolean silent;
|
||||
Boolean emsg_silent;
|
||||
Boolean unsilent;
|
||||
Dictionary filter;
|
||||
Boolean sandbox;
|
||||
Boolean noautocmd;
|
||||
Boolean browse;
|
||||
Boolean confirm;
|
||||
Boolean hide;
|
||||
Boolean horizontal;
|
||||
Boolean keepalt;
|
||||
Boolean keepjumps;
|
||||
Boolean keepmarks;
|
||||
Boolean keeppatterns;
|
||||
Boolean lockmarks;
|
||||
Boolean noswapfile;
|
||||
Integer tab;
|
||||
Integer verbose;
|
||||
Boolean vertical;
|
||||
String split;
|
||||
} Dict(cmd_mods);
|
||||
|
||||
typedef struct {
|
||||
Object pattern;
|
||||
Object force;
|
||||
OptionalKeys is_set__cmd_mods_filter_;
|
||||
String pattern;
|
||||
Boolean force;
|
||||
} Dict(cmd_mods_filter);
|
||||
|
||||
typedef struct {
|
||||
Object output;
|
||||
Boolean output;
|
||||
} Dict(cmd_opts);
|
||||
|
||||
typedef struct {
|
||||
Object verbose;
|
||||
Boolean verbose;
|
||||
} Dict(echo_opts);
|
||||
|
||||
typedef struct {
|
||||
Object output;
|
||||
Boolean output;
|
||||
} Dict(exec_opts);
|
||||
|
||||
#endif // NVIM_API_KEYSETS_H
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "nvim/api/options.h"
|
||||
#include "nvim/api/private/defs.h"
|
||||
#include "nvim/api/private/dispatch.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/api/private/validate.h"
|
||||
#include "nvim/autocmd.h"
|
||||
@ -26,14 +27,11 @@
|
||||
static int validate_option_value_args(Dict(option) *opts, char *name, int *scope, int *opt_type,
|
||||
void **from, char **filetype, Error *err)
|
||||
{
|
||||
if (HAS_KEY(opts->scope)) {
|
||||
VALIDATE_T("scope", kObjectTypeString, opts->scope.type, {
|
||||
return FAIL;
|
||||
});
|
||||
|
||||
if (!strcmp(opts->scope.data.string.data, "local")) {
|
||||
#define HAS_KEY_X(d, v) HAS_KEY(d, option, v)
|
||||
if (HAS_KEY_X(opts, scope)) {
|
||||
if (!strcmp(opts->scope.data, "local")) {
|
||||
*scope = OPT_LOCAL;
|
||||
} else if (!strcmp(opts->scope.data.string.data, "global")) {
|
||||
} else if (!strcmp(opts->scope.data, "global")) {
|
||||
*scope = OPT_GLOBAL;
|
||||
} else {
|
||||
VALIDATE_EXP(false, "scope", "'local' or 'global'", NULL, {
|
||||
@ -44,51 +42,40 @@ static int validate_option_value_args(Dict(option) *opts, char *name, int *scope
|
||||
|
||||
*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 (filetype != NULL && HAS_KEY_X(opts, filetype)) {
|
||||
*filetype = opts->filetype.data;
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->win)) {
|
||||
VALIDATE_T_HANDLE("win", kObjectTypeWindow, opts->win.type, {
|
||||
return FAIL;
|
||||
});
|
||||
|
||||
if (HAS_KEY_X(opts, win)) {
|
||||
*opt_type = SREQ_WIN;
|
||||
*from = find_window_by_handle((int)opts->win.data.integer, err);
|
||||
*from = find_window_by_handle(opts->win, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->buf)) {
|
||||
VALIDATE_T_HANDLE("buf", kObjectTypeBuffer, opts->buf.type, {
|
||||
return FAIL;
|
||||
});
|
||||
|
||||
if (HAS_KEY_X(opts, buf)) {
|
||||
*scope = OPT_LOCAL;
|
||||
*opt_type = SREQ_BUF;
|
||||
*from = find_buffer_by_handle((int)opts->buf.data.integer, err);
|
||||
*from = find_buffer_by_handle(opts->buf, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
VALIDATE((!HAS_KEY(opts->filetype)
|
||||
|| !(HAS_KEY(opts->buf) || HAS_KEY(opts->scope) || HAS_KEY(opts->win))),
|
||||
VALIDATE((!HAS_KEY_X(opts, filetype)
|
||||
|| !(HAS_KEY_X(opts, buf) || HAS_KEY_X(opts, scope) || HAS_KEY_X(opts, win))),
|
||||
"%s", "cannot use 'filetype' with 'scope', 'buf' or 'win'", {
|
||||
return FAIL;
|
||||
});
|
||||
|
||||
VALIDATE((!HAS_KEY(opts->scope) || !HAS_KEY(opts->buf)), "%s",
|
||||
VALIDATE((!HAS_KEY_X(opts, scope) || !HAS_KEY_X(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'", {
|
||||
VALIDATE((!HAS_KEY_X(opts, win) || !HAS_KEY_X(opts, buf)),
|
||||
"%s", "cannot use both 'buf' and 'win'", {
|
||||
return FAIL;
|
||||
});
|
||||
|
||||
@ -111,6 +98,7 @@ static int validate_option_value_args(Dict(option) *opts, char *name, int *scope
|
||||
}
|
||||
|
||||
return OK;
|
||||
#undef HAS_KEY_X
|
||||
}
|
||||
|
||||
/// Create a dummy buffer and run the FileType autocmd on it.
|
||||
|
@ -124,10 +124,20 @@ struct key_value_pair {
|
||||
Object value;
|
||||
};
|
||||
|
||||
typedef Object *(*field_hash)(void *retval, const char *str, size_t len);
|
||||
typedef uint64_t OptionalKeys;
|
||||
|
||||
// this is the prefix of all keysets with optional keys
|
||||
typedef struct {
|
||||
OptionalKeys is_set_;
|
||||
} OptKeySet;
|
||||
|
||||
typedef struct {
|
||||
char *str;
|
||||
size_t ptr_off;
|
||||
ObjectType type; // kObjectTypeNil == untyped
|
||||
int opt_index;
|
||||
} KeySetLink;
|
||||
|
||||
typedef KeySetLink *(*FieldHashfn)(const char *str, size_t len);
|
||||
|
||||
#endif // NVIM_API_PRIVATE_DEFS_H
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "nvim/api/private/converter.h"
|
||||
#include "nvim/api/private/defs.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/api/private/validate.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/buffer_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
@ -915,17 +916,84 @@ free_exit:
|
||||
return (HlMessage)KV_INITIAL_VALUE;
|
||||
}
|
||||
|
||||
bool api_dict_to_keydict(void *rv, field_hash hashy, Dictionary dict, Error *err)
|
||||
// see also nlua_pop_keydict for the lua specific implementation
|
||||
bool api_dict_to_keydict(void *retval, FieldHashfn hashy, Dictionary dict, Error *err)
|
||||
{
|
||||
for (size_t i = 0; i < dict.size; i++) {
|
||||
String k = dict.items[i].key;
|
||||
Object *field = hashy(rv, k.data, k.size);
|
||||
KeySetLink *field = hashy(k.data, k.size);
|
||||
if (!field) {
|
||||
api_set_error(err, kErrorTypeValidation, "Invalid key: '%.*s'", (int)k.size, k.data);
|
||||
return false;
|
||||
}
|
||||
|
||||
*field = dict.items[i].value;
|
||||
if (field->opt_index >= 0) {
|
||||
OptKeySet *ks = (OptKeySet *)retval;
|
||||
ks->is_set_ |= (1ULL << field->opt_index);
|
||||
}
|
||||
|
||||
char *mem = ((char *)retval + field->ptr_off);
|
||||
Object *value = &dict.items[i].value;
|
||||
if (field->type == kObjectTypeNil) {
|
||||
*(Object *)mem = *value;
|
||||
} else if (field->type == kObjectTypeInteger) {
|
||||
VALIDATE_T(field->str, kObjectTypeInteger, value->type, {
|
||||
return false;
|
||||
});
|
||||
*(Integer *)mem = value->data.integer;
|
||||
} else if (field->type == kObjectTypeFloat) {
|
||||
Float *val = (Float *)mem;
|
||||
if (value->type == kObjectTypeInteger) {
|
||||
*val = (Float)value->data.integer;
|
||||
} else {
|
||||
VALIDATE_T(field->str, kObjectTypeFloat, value->type, {
|
||||
return false;
|
||||
});
|
||||
*val = value->data.floating;
|
||||
}
|
||||
} else if (field->type == kObjectTypeBoolean) {
|
||||
// caller should check HAS_KEY to override the nil behavior, or GET_BOOL_OR_TRUE
|
||||
// to directly use true when nil
|
||||
*(Boolean *)mem = api_object_to_bool(*value, field->str, false, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return false;
|
||||
}
|
||||
} else if (field->type == kObjectTypeString) {
|
||||
VALIDATE_T(field->str, kObjectTypeString, value->type, {
|
||||
return false;
|
||||
});
|
||||
*(String *)mem = value->data.string;
|
||||
} else if (field->type == kObjectTypeArray) {
|
||||
VALIDATE_T(field->str, kObjectTypeArray, value->type, {
|
||||
return false;
|
||||
});
|
||||
*(Array *)mem = value->data.array;
|
||||
} else if (field->type == kObjectTypeDictionary) {
|
||||
Dictionary *val = (Dictionary *)mem;
|
||||
// allow empty array as empty dict for lua (directly or via lua-client RPC)
|
||||
if (value->type == kObjectTypeArray && value->data.array.size == 0) {
|
||||
*val = (Dictionary)ARRAY_DICT_INIT;
|
||||
} else if (value->type == kObjectTypeDictionary) {
|
||||
*val = value->data.dictionary;
|
||||
} else {
|
||||
api_err_exp(err, field->str, api_typename(field->type), api_typename(value->type));
|
||||
return false;
|
||||
}
|
||||
} else if (field->type == kObjectTypeBuffer || field->type == kObjectTypeWindow
|
||||
|| field->type == kObjectTypeTabpage) {
|
||||
if (value->type == kObjectTypeInteger || value->type == field->type) {
|
||||
*(handle_T *)mem = (handle_T)value->data.integer;
|
||||
} else {
|
||||
api_err_exp(err, field->str, api_typename(field->type), api_typename(value->type));
|
||||
return false;
|
||||
}
|
||||
} else if (field->type == kObjectTypeLuaRef) {
|
||||
api_set_error(err, kErrorTypeValidation, "Invalid key: '%.*s' is only allowed from Lua",
|
||||
(int)k.size, k.data);
|
||||
return false;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -934,7 +1002,18 @@ bool api_dict_to_keydict(void *rv, field_hash hashy, Dictionary dict, Error *err
|
||||
void api_free_keydict(void *dict, KeySetLink *table)
|
||||
{
|
||||
for (size_t i = 0; table[i].str; i++) {
|
||||
api_free_object(*(Object *)((char *)dict + table[i].ptr_off));
|
||||
char *mem = ((char *)dict + table[i].ptr_off);
|
||||
if (table[i].type == kObjectTypeNil) {
|
||||
api_free_object(*(Object *)mem);
|
||||
} else if (table[i].type == kObjectTypeString) {
|
||||
api_free_string(*(String *)mem);
|
||||
} else if (table[i].type == kObjectTypeArray) {
|
||||
api_free_array(*(Array *)mem);
|
||||
} else if (table[i].type == kObjectTypeDictionary) {
|
||||
api_free_dictionary(*(Dictionary *)mem);
|
||||
} else if (table[i].type == kObjectTypeLuaRef) {
|
||||
api_free_luaref(*(LuaRef *)mem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,8 +63,9 @@
|
||||
#define NIL ((Object)OBJECT_INIT)
|
||||
#define NULL_STRING ((String)STRING_INIT)
|
||||
|
||||
// currently treat key=vim.NIL as if the key was missing
|
||||
#define HAS_KEY(o) ((o).type != kObjectTypeNil)
|
||||
#define HAS_KEY(d, typ, key) (((d)->is_set__##typ##_ & (1 << KEYSET_OPTIDX_##typ##__##key)) != 0)
|
||||
|
||||
#define GET_BOOL_OR_TRUE(d, typ, key) (HAS_KEY(d, typ, key) ? (d)->key : true)
|
||||
|
||||
#define PUT(dict, k, v) \
|
||||
kv_push(dict, ((KeyValuePair) { .key = cstr_to_string(k), .value = v }))
|
||||
|
@ -558,16 +558,15 @@ ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, E
|
||||
FUNC_API_SINCE(8)
|
||||
FUNC_API_FAST
|
||||
{
|
||||
bool is_lua = api_object_to_bool(opts->is_lua, "is_lua", false, err);
|
||||
bool source = api_object_to_bool(opts->do_source, "do_source", false, err);
|
||||
VALIDATE((!source || nlua_is_deferred_safe()), "%s", "'do_source' used in fast callback", {});
|
||||
VALIDATE((!opts->do_source || nlua_is_deferred_safe()), "%s", "'do_source' used in fast callback",
|
||||
{});
|
||||
if (ERROR_SET(err)) {
|
||||
return (Array)ARRAY_DICT_INIT;
|
||||
}
|
||||
|
||||
ArrayOf(String) res = runtime_get_named(is_lua, pat, all);
|
||||
ArrayOf(String) res = runtime_get_named(opts->is_lua, pat, all);
|
||||
|
||||
if (source) {
|
||||
if (opts->do_source) {
|
||||
for (size_t i = 0; i < res.size; i++) {
|
||||
String name = res.items[i].data.string;
|
||||
(void)do_source(name.data, false, DOSO_NONE, NULL);
|
||||
@ -718,15 +717,13 @@ void nvim_echo(Array chunks, Boolean history, Dict(echo_opts) *opts, Error *err)
|
||||
goto error;
|
||||
}
|
||||
|
||||
bool verbose = api_object_to_bool(opts->verbose, "verbose", false, err);
|
||||
|
||||
if (verbose) {
|
||||
if (opts->verbose) {
|
||||
verbose_enter();
|
||||
}
|
||||
|
||||
msg_multiattr(hl_msg, history ? "echomsg" : "echo", history);
|
||||
|
||||
if (verbose) {
|
||||
if (opts->verbose) {
|
||||
verbose_leave();
|
||||
verbose_stop(); // flush now
|
||||
}
|
||||
@ -1323,11 +1320,8 @@ Dictionary nvim_get_context(Dict(context) *opts, Error *err)
|
||||
FUNC_API_SINCE(6)
|
||||
{
|
||||
Array types = ARRAY_DICT_INIT;
|
||||
if (HAS_KEY(opts->types)) {
|
||||
VALIDATE_T("types", kObjectTypeArray, opts->types.type, {
|
||||
return (Dictionary)ARRAY_DICT_INIT;
|
||||
});
|
||||
types = opts->types.data.array;
|
||||
if (HAS_KEY(opts, context, types)) {
|
||||
types = opts->types;
|
||||
}
|
||||
|
||||
int int_types = types.size > 0 ? 0 : kCtxAll;
|
||||
@ -2091,12 +2085,8 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
|
||||
|
||||
int maxwidth;
|
||||
int fillchar = 0;
|
||||
int use_bools = 0;
|
||||
int statuscol_lnum = 0;
|
||||
Window window = 0;
|
||||
bool use_winbar = false;
|
||||
bool use_tabline = false;
|
||||
bool highlights = false;
|
||||
|
||||
if (str.size < 2 || memcmp(str.data, "%!", 2) != 0) {
|
||||
const char *const errmsg = check_stl_option(str.data);
|
||||
@ -2105,58 +2095,28 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
|
||||
});
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->winid)) {
|
||||
VALIDATE_T("winid", kObjectTypeInteger, opts->winid.type, {
|
||||
return result;
|
||||
});
|
||||
|
||||
window = (Window)opts->winid.data.integer;
|
||||
if (HAS_KEY(opts, eval_statusline, winid)) {
|
||||
window = opts->winid;
|
||||
}
|
||||
if (HAS_KEY(opts->fillchar)) {
|
||||
VALIDATE_T("fillchar", kObjectTypeString, opts->fillchar.type, {
|
||||
return result;
|
||||
});
|
||||
VALIDATE_EXP((opts->fillchar.data.string.size != 0
|
||||
&& ((size_t)utf_ptr2len(opts->fillchar.data.string.data)
|
||||
== opts->fillchar.data.string.size)),
|
||||
if (HAS_KEY(opts, eval_statusline, fillchar)) {
|
||||
VALIDATE_EXP((*opts->fillchar.data != 0
|
||||
&& ((size_t)utf_ptr2len(opts->fillchar.data) == opts->fillchar.size)),
|
||||
"fillchar", "single character", NULL, {
|
||||
return result;
|
||||
});
|
||||
fillchar = utf_ptr2char(opts->fillchar.data.string.data);
|
||||
}
|
||||
if (HAS_KEY(opts->highlights)) {
|
||||
highlights = api_object_to_bool(opts->highlights, "highlights", false, err);
|
||||
|
||||
if (ERROR_SET(err)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (HAS_KEY(opts->use_winbar)) {
|
||||
use_winbar = api_object_to_bool(opts->use_winbar, "use_winbar", false, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return result;
|
||||
}
|
||||
use_bools++;
|
||||
}
|
||||
if (HAS_KEY(opts->use_tabline)) {
|
||||
use_tabline = api_object_to_bool(opts->use_tabline, "use_tabline", false, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return result;
|
||||
}
|
||||
use_bools++;
|
||||
fillchar = utf_ptr2char(opts->fillchar.data);
|
||||
}
|
||||
|
||||
win_T *wp = use_tabline ? curwin : find_window_by_handle(window, err);
|
||||
int use_bools = (int)opts->use_winbar + (int)opts->use_tabline;
|
||||
|
||||
win_T *wp = opts->use_tabline ? curwin : find_window_by_handle(window, err);
|
||||
if (wp == NULL) {
|
||||
api_set_error(err, kErrorTypeException, "unknown winid %d", window);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->use_statuscol_lnum)) {
|
||||
VALIDATE_T("use_statuscol_lnum", kObjectTypeInteger, opts->use_statuscol_lnum.type, {
|
||||
return result;
|
||||
});
|
||||
statuscol_lnum = (int)opts->use_statuscol_lnum.data.integer;
|
||||
if (HAS_KEY(opts, eval_statusline, use_statuscol_lnum)) {
|
||||
statuscol_lnum = (int)opts->use_statuscol_lnum;
|
||||
VALIDATE_RANGE(statuscol_lnum > 0 && statuscol_lnum <= wp->w_buffer->b_ml.ml_line_count,
|
||||
"use_statuscol_lnum", {
|
||||
return result;
|
||||
@ -2172,11 +2132,11 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
|
||||
statuscol_T statuscol = { 0 };
|
||||
SignTextAttrs sattrs[SIGN_SHOW_MAX] = { 0 };
|
||||
|
||||
if (use_tabline) {
|
||||
if (opts->use_tabline) {
|
||||
fillchar = ' ';
|
||||
} else {
|
||||
if (fillchar == 0) {
|
||||
if (use_winbar) {
|
||||
if (opts->use_winbar) {
|
||||
fillchar = wp->w_p_fcs_chars.wbr;
|
||||
} else {
|
||||
int attr;
|
||||
@ -2220,15 +2180,12 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
|
||||
}
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->maxwidth)) {
|
||||
VALIDATE_T("maxwidth", kObjectTypeInteger, opts->maxwidth.type, {
|
||||
return result;
|
||||
});
|
||||
|
||||
maxwidth = (int)opts->maxwidth.data.integer;
|
||||
if (HAS_KEY(opts, eval_statusline, maxwidth)) {
|
||||
maxwidth = (int)opts->maxwidth;
|
||||
} else {
|
||||
maxwidth = statuscol_lnum ? win_col_off(wp)
|
||||
: (use_tabline || (!use_winbar && global_stl_height() > 0)) ? Columns : wp->w_width;
|
||||
: (opts->use_tabline
|
||||
|| (!opts->use_winbar && global_stl_height() > 0)) ? Columns : wp->w_width;
|
||||
}
|
||||
|
||||
char buf[MAXPATHL];
|
||||
@ -2246,7 +2203,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
|
||||
0,
|
||||
fillchar,
|
||||
maxwidth,
|
||||
highlights ? &hltab : NULL,
|
||||
opts->highlights ? &hltab : NULL,
|
||||
NULL,
|
||||
statuscol_lnum ? &statuscol : NULL);
|
||||
|
||||
@ -2255,7 +2212,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
|
||||
// Restore original value of 'cursorbind'
|
||||
wp->w_p_crb = p_crb_save;
|
||||
|
||||
if (highlights) {
|
||||
if (opts->highlights) {
|
||||
Array hl_values = ARRAY_DICT_INIT;
|
||||
const char *grpname;
|
||||
char user_group[15]; // strlen("User") + strlen("2147483647") + NUL
|
||||
@ -2264,7 +2221,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
|
||||
// add the default highlight at the beginning of the highlight list
|
||||
if (hltab->start == NULL || (hltab->start - buf) != 0) {
|
||||
Dictionary hl_info = ARRAY_DICT_INIT;
|
||||
grpname = get_default_stl_hl(use_tabline ? NULL : wp, use_winbar, stc_hl_id);
|
||||
grpname = get_default_stl_hl(opts->use_tabline ? NULL : wp, opts->use_winbar, stc_hl_id);
|
||||
|
||||
PUT(hl_info, "start", INTEGER_OBJ(0));
|
||||
PUT(hl_info, "group", CSTR_TO_OBJ(grpname));
|
||||
@ -2278,7 +2235,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
|
||||
PUT(hl_info, "start", INTEGER_OBJ(sp->start - buf));
|
||||
|
||||
if (sp->userhl == 0) {
|
||||
grpname = get_default_stl_hl(use_tabline ? NULL : wp, use_winbar, stc_hl_id);
|
||||
grpname = get_default_stl_hl(opts->use_tabline ? NULL : wp, opts->use_winbar, stc_hl_id);
|
||||
} else if (sp->userhl < 0) {
|
||||
grpname = syn_id2name(-sp->userhl);
|
||||
} else {
|
||||
|
@ -61,7 +61,7 @@ Dictionary nvim_exec2(uint64_t channel_id, String src, Dict(exec_opts) *opts, Er
|
||||
return result;
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->output) && api_object_to_bool(opts->output, "opts.output", false, err)) {
|
||||
if (opts->output) {
|
||||
PUT(result, "output", STRING_OBJ(output));
|
||||
}
|
||||
|
||||
@ -70,19 +70,17 @@ Dictionary nvim_exec2(uint64_t channel_id, String src, Dict(exec_opts) *opts, Er
|
||||
|
||||
String exec_impl(uint64_t channel_id, String src, Dict(exec_opts) *opts, Error *err)
|
||||
{
|
||||
Boolean output = api_object_to_bool(opts->output, "opts.output", false, err);
|
||||
|
||||
const int save_msg_silent = msg_silent;
|
||||
garray_T *const save_capture_ga = capture_ga;
|
||||
const int save_msg_col = msg_col;
|
||||
garray_T capture_local;
|
||||
if (output) {
|
||||
if (opts->output) {
|
||||
ga_init(&capture_local, 1, 80);
|
||||
capture_ga = &capture_local;
|
||||
}
|
||||
|
||||
try_start();
|
||||
if (output) {
|
||||
if (opts->output) {
|
||||
msg_silent++;
|
||||
msg_col = 0; // prevent leading spaces
|
||||
}
|
||||
@ -90,7 +88,7 @@ String exec_impl(uint64_t channel_id, String src, Dict(exec_opts) *opts, Error *
|
||||
const sctx_T save_current_sctx = api_set_sctx(channel_id);
|
||||
|
||||
do_source_str(src.data, "nvim_exec2()");
|
||||
if (output) {
|
||||
if (opts->output) {
|
||||
capture_ga = save_capture_ga;
|
||||
msg_silent = save_msg_silent;
|
||||
// Put msg_col back where it was, since nothing should have been written.
|
||||
@ -104,7 +102,7 @@ String exec_impl(uint64_t channel_id, String src, Dict(exec_opts) *opts, Error *
|
||||
goto theend;
|
||||
}
|
||||
|
||||
if (output && capture_local.ga_len > 1) {
|
||||
if (opts->output && capture_local.ga_len > 1) {
|
||||
String s = (String){
|
||||
.data = capture_local.ga_data,
|
||||
.size = (size_t)capture_local.ga_len,
|
||||
@ -118,7 +116,7 @@ String exec_impl(uint64_t channel_id, String src, Dict(exec_opts) *opts, Error *
|
||||
return s; // Caller will free the memory.
|
||||
}
|
||||
theend:
|
||||
if (output) {
|
||||
if (opts->output) {
|
||||
ga_clear(&capture_local);
|
||||
}
|
||||
return (String)STRING_INIT;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "klib/kvec.h"
|
||||
#include "nvim/api/extmark.h"
|
||||
#include "nvim/api/private/defs.h"
|
||||
#include "nvim/api/private/dispatch.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/api/win_config.h"
|
||||
#include "nvim/ascii.h"
|
||||
@ -231,7 +232,7 @@ void nvim_win_set_config(Window window, Dict(float_config) *config, Error *err)
|
||||
win_config_float(win, fconfig);
|
||||
win->w_pos_changed = true;
|
||||
}
|
||||
if (HAS_KEY(config->style)) {
|
||||
if (HAS_KEY(config, float_config, style)) {
|
||||
if (fconfig.style == kWinStyleMinimal) {
|
||||
win_set_minimal_style(win);
|
||||
didset_window_options(win, true);
|
||||
@ -380,12 +381,8 @@ static bool parse_float_bufpos(Array bufpos, lpos_T *out)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void parse_border_title(Object title, Object title_pos, FloatConfig *fconfig, Error *err)
|
||||
static void parse_border_title(Object title, FloatConfig *fconfig, Error *err)
|
||||
{
|
||||
if (!parse_title_pos(title_pos, fconfig, err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (title.type == kObjectTypeString) {
|
||||
if (title.data.string.size == 0) {
|
||||
fconfig->title = false;
|
||||
@ -415,24 +412,14 @@ static void parse_border_title(Object title, Object title_pos, FloatConfig *fcon
|
||||
fconfig->title = true;
|
||||
}
|
||||
|
||||
static bool parse_title_pos(Object title_pos, FloatConfig *fconfig, Error *err)
|
||||
static bool parse_title_pos(String title_pos, FloatConfig *fconfig, Error *err)
|
||||
{
|
||||
if (!HAS_KEY(title_pos)) {
|
||||
if (title_pos.size == 0) {
|
||||
fconfig->title_pos = kAlignLeft;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (title_pos.type != kObjectTypeString) {
|
||||
api_set_error(err, kErrorTypeValidation, "title_pos must be string");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (title_pos.data.string.size == 0) {
|
||||
fconfig->title_pos = kAlignLeft;
|
||||
return true;
|
||||
}
|
||||
|
||||
char *pos = title_pos.data.string.data;
|
||||
char *pos = title_pos.data;
|
||||
|
||||
if (strequal(pos, "left")) {
|
||||
fconfig->title_pos = kAlignLeft;
|
||||
@ -559,110 +546,90 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
|
||||
static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig, bool reconf,
|
||||
bool new_win, Error *err)
|
||||
{
|
||||
#define HAS_KEY_X(d, key) HAS_KEY(d, float_config, key)
|
||||
bool has_relative = false, relative_is_win = false;
|
||||
if (config->relative.type == kObjectTypeString) {
|
||||
// ignore empty string, to match nvim_win_get_config
|
||||
if (config->relative.data.string.size > 0) {
|
||||
if (!parse_float_relative(config->relative.data.string, &fconfig->relative)) {
|
||||
api_set_error(err, kErrorTypeValidation, "Invalid value of 'relative' key");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(HAS_KEY(config->row) && HAS_KEY(config->col)) && !HAS_KEY(config->bufpos)) {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"'relative' requires 'row'/'col' or 'bufpos'");
|
||||
return false;
|
||||
}
|
||||
|
||||
has_relative = true;
|
||||
fconfig->external = false;
|
||||
if (fconfig->relative == kFloatRelativeWindow) {
|
||||
relative_is_win = true;
|
||||
fconfig->bufpos.lnum = -1;
|
||||
}
|
||||
// ignore empty string, to match nvim_win_get_config
|
||||
if (HAS_KEY_X(config, relative) && config->relative.size > 0) {
|
||||
if (!parse_float_relative(config->relative, &fconfig->relative)) {
|
||||
api_set_error(err, kErrorTypeValidation, "Invalid value of 'relative' key");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(HAS_KEY_X(config, row) && HAS_KEY_X(config, col)) && !HAS_KEY_X(config, bufpos)) {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"'relative' requires 'row'/'col' or 'bufpos'");
|
||||
return false;
|
||||
}
|
||||
|
||||
has_relative = true;
|
||||
fconfig->external = false;
|
||||
if (fconfig->relative == kFloatRelativeWindow) {
|
||||
relative_is_win = true;
|
||||
fconfig->bufpos.lnum = -1;
|
||||
}
|
||||
} else if (HAS_KEY(config->relative)) {
|
||||
api_set_error(err, kErrorTypeValidation, "'relative' key must be String");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (config->anchor.type == kObjectTypeString) {
|
||||
if (!parse_float_anchor(config->anchor.data.string, &fconfig->anchor)) {
|
||||
if (HAS_KEY_X(config, anchor)) {
|
||||
if (!parse_float_anchor(config->anchor, &fconfig->anchor)) {
|
||||
api_set_error(err, kErrorTypeValidation, "Invalid value of 'anchor' key");
|
||||
return false;
|
||||
}
|
||||
} else if (HAS_KEY(config->anchor)) {
|
||||
api_set_error(err, kErrorTypeValidation, "'anchor' key must be String");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HAS_KEY(config->row)) {
|
||||
if (HAS_KEY_X(config, row)) {
|
||||
if (!has_relative) {
|
||||
api_set_error(err, kErrorTypeValidation, "non-float cannot have 'row'");
|
||||
return false;
|
||||
} else if (config->row.type == kObjectTypeInteger) {
|
||||
fconfig->row = (double)config->row.data.integer;
|
||||
} else if (config->row.type == kObjectTypeFloat) {
|
||||
fconfig->row = config->row.data.floating;
|
||||
} else {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"'row' key must be Integer or Float");
|
||||
return false;
|
||||
}
|
||||
fconfig->row = config->row;
|
||||
}
|
||||
|
||||
if (HAS_KEY(config->col)) {
|
||||
if (HAS_KEY_X(config, col)) {
|
||||
if (!has_relative) {
|
||||
api_set_error(err, kErrorTypeValidation, "non-float cannot have 'col'");
|
||||
return false;
|
||||
} else if (config->col.type == kObjectTypeInteger) {
|
||||
fconfig->col = (double)config->col.data.integer;
|
||||
} else if (config->col.type == kObjectTypeFloat) {
|
||||
fconfig->col = config->col.data.floating;
|
||||
} else {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"'col' key must be Integer or Float");
|
||||
return false;
|
||||
}
|
||||
fconfig->col = config->col;
|
||||
}
|
||||
|
||||
if (HAS_KEY(config->bufpos)) {
|
||||
if (HAS_KEY_X(config, bufpos)) {
|
||||
if (!has_relative) {
|
||||
api_set_error(err, kErrorTypeValidation, "non-float cannot have 'bufpos'");
|
||||
return false;
|
||||
} else if (config->bufpos.type == kObjectTypeArray) {
|
||||
if (!parse_float_bufpos(config->bufpos.data.array, &fconfig->bufpos)) {
|
||||
} else {
|
||||
if (!parse_float_bufpos(config->bufpos, &fconfig->bufpos)) {
|
||||
api_set_error(err, kErrorTypeValidation, "Invalid value of 'bufpos' key");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!HAS_KEY(config->row)) {
|
||||
if (!HAS_KEY_X(config, row)) {
|
||||
fconfig->row = (fconfig->anchor & kFloatAnchorSouth) ? 0 : 1;
|
||||
}
|
||||
if (!HAS_KEY(config->col)) {
|
||||
if (!HAS_KEY_X(config, col)) {
|
||||
fconfig->col = 0;
|
||||
}
|
||||
} else {
|
||||
api_set_error(err, kErrorTypeValidation, "'bufpos' key must be Array");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (config->width.type == kObjectTypeInteger && config->width.data.integer > 0) {
|
||||
fconfig->width = (int)config->width.data.integer;
|
||||
} else if (HAS_KEY(config->width)) {
|
||||
api_set_error(err, kErrorTypeValidation, "'width' key must be a positive Integer");
|
||||
return false;
|
||||
if (HAS_KEY_X(config, width)) {
|
||||
if (config->width > 0) {
|
||||
fconfig->width = (int)config->width;
|
||||
} else {
|
||||
api_set_error(err, kErrorTypeValidation, "'width' key must be a positive Integer");
|
||||
return false;
|
||||
}
|
||||
} else if (!reconf) {
|
||||
api_set_error(err, kErrorTypeValidation, "Must specify 'width'");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (config->height.type == kObjectTypeInteger && config->height.data.integer > 0) {
|
||||
fconfig->height = (int)config->height.data.integer;
|
||||
} else if (HAS_KEY(config->height)) {
|
||||
api_set_error(err, kErrorTypeValidation, "'height' key must be a positive Integer");
|
||||
return false;
|
||||
if (HAS_KEY_X(config, height)) {
|
||||
if (config->height > 0) {
|
||||
fconfig->height = (int)config->height;
|
||||
} else {
|
||||
api_set_error(err, kErrorTypeValidation, "'height' key must be a positive Integer");
|
||||
return false;
|
||||
}
|
||||
} else if (!reconf) {
|
||||
api_set_error(err, kErrorTypeValidation, "Must specify 'height'");
|
||||
return false;
|
||||
@ -670,26 +637,20 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig,
|
||||
|
||||
if (relative_is_win) {
|
||||
fconfig->window = curwin->handle;
|
||||
if (config->win.type == kObjectTypeInteger || config->win.type == kObjectTypeWindow) {
|
||||
if (config->win.data.integer > 0) {
|
||||
fconfig->window = (Window)config->win.data.integer;
|
||||
if (HAS_KEY_X(config, win)) {
|
||||
if (config->win > 0) {
|
||||
fconfig->window = config->win;
|
||||
}
|
||||
} else if (HAS_KEY(config->win)) {
|
||||
api_set_error(err, kErrorTypeValidation, "'win' key must be Integer or Window");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (HAS_KEY(config->win)) {
|
||||
if (HAS_KEY_X(config, win)) {
|
||||
api_set_error(err, kErrorTypeValidation, "'win' key is only valid with relative='win'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (HAS_KEY(config->external)) {
|
||||
fconfig->external = api_object_to_bool(config->external, "'external' key", false, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return false;
|
||||
}
|
||||
if (HAS_KEY_X(config, external)) {
|
||||
fconfig->external = config->external;
|
||||
if (has_relative && fconfig->external) {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"Only one of 'relative' and 'external' must be used");
|
||||
@ -708,30 +669,22 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HAS_KEY(config->focusable)) {
|
||||
fconfig->focusable = api_object_to_bool(config->focusable, "'focusable' key", false, err);
|
||||
if (ERROR_SET(err)) {
|
||||
if (HAS_KEY_X(config, focusable)) {
|
||||
fconfig->focusable = config->focusable;
|
||||
}
|
||||
|
||||
if (HAS_KEY_X(config, zindex)) {
|
||||
if (config->zindex > 0) {
|
||||
fconfig->zindex = (int)config->zindex;
|
||||
} else {
|
||||
api_set_error(err, kErrorTypeValidation, "'zindex' key must be a positive Integer");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (config->zindex.type == kObjectTypeInteger && config->zindex.data.integer > 0) {
|
||||
fconfig->zindex = (int)config->zindex.data.integer;
|
||||
} else if (HAS_KEY(config->zindex)) {
|
||||
api_set_error(err, kErrorTypeValidation, "'zindex' key must be a positive Integer");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HAS_KEY(config->title_pos)) {
|
||||
if (!HAS_KEY(config->title)) {
|
||||
api_set_error(err, kErrorTypeException, "title_pos requires title to be set");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (HAS_KEY(config->title)) {
|
||||
if (HAS_KEY_X(config, title)) {
|
||||
// title only work with border
|
||||
if (!HAS_KEY(config->border) && !fconfig->border) {
|
||||
if (!HAS_KEY_X(config, border) && !fconfig->border) {
|
||||
api_set_error(err, kErrorTypeException, "title requires border to be set");
|
||||
return false;
|
||||
}
|
||||
@ -739,42 +692,49 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig,
|
||||
if (fconfig->title) {
|
||||
clear_virttext(&fconfig->title_chunks);
|
||||
}
|
||||
parse_border_title(config->title, config->title_pos, fconfig, err);
|
||||
|
||||
parse_border_title(config->title, fconfig, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// handles unset 'title_pos' same as empty string
|
||||
if (!parse_title_pos(config->title_pos, fconfig, err)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (HAS_KEY_X(config, title_pos)) {
|
||||
api_set_error(err, kErrorTypeException, "title_pos requires title to be set");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (HAS_KEY(config->border)) {
|
||||
if (HAS_KEY_X(config, border)) {
|
||||
parse_border_style(config->border, fconfig, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (config->style.type == kObjectTypeString) {
|
||||
if (config->style.data.string.data[0] == NUL) {
|
||||
if (HAS_KEY_X(config, style)) {
|
||||
if (config->style.data[0] == NUL) {
|
||||
fconfig->style = kWinStyleUnused;
|
||||
} else if (striequal(config->style.data.string.data, "minimal")) {
|
||||
} else if (striequal(config->style.data, "minimal")) {
|
||||
fconfig->style = kWinStyleMinimal;
|
||||
} else {
|
||||
api_set_error(err, kErrorTypeValidation, "Invalid value of 'style' key");
|
||||
return false;
|
||||
}
|
||||
} else if (HAS_KEY(config->style)) {
|
||||
api_set_error(err, kErrorTypeValidation, "'style' key must be String");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HAS_KEY(config->noautocmd)) {
|
||||
if (HAS_KEY_X(config, noautocmd)) {
|
||||
if (!new_win) {
|
||||
api_set_error(err, kErrorTypeValidation, "Invalid key: 'noautocmd'");
|
||||
return false;
|
||||
}
|
||||
fconfig->noautocmd = api_object_to_bool(config->noautocmd, "'noautocmd' key", false, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return false;
|
||||
}
|
||||
fconfig->noautocmd = config->noautocmd;
|
||||
}
|
||||
|
||||
return true;
|
||||
#undef HAS_KEY_X
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "nvim/api/private/defs.h"
|
||||
#include "nvim/api/private/dispatch.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/api/private/validate.h"
|
||||
#include "nvim/api/window.h"
|
||||
@ -513,18 +514,12 @@ Dictionary nvim_win_text_height(Window window, Dict(win_text_height) *opts, Aren
|
||||
|
||||
bool oob = false;
|
||||
|
||||
if (HAS_KEY(opts->start_row)) {
|
||||
VALIDATE_T("start_row", kObjectTypeInteger, opts->start_row.type, {
|
||||
return rv;
|
||||
});
|
||||
start_lnum = (linenr_T)normalize_index(buf, opts->start_row.data.integer, false, &oob);
|
||||
if (HAS_KEY(opts, win_text_height, start_row)) {
|
||||
start_lnum = (linenr_T)normalize_index(buf, opts->start_row, false, &oob);
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->end_row)) {
|
||||
VALIDATE_T("end_row", kObjectTypeInteger, opts->end_row.type, {
|
||||
return rv;
|
||||
});
|
||||
end_lnum = (linenr_T)normalize_index(buf, opts->end_row.data.integer, false, &oob);
|
||||
if (HAS_KEY(opts, win_text_height, end_row)) {
|
||||
end_lnum = (linenr_T)normalize_index(buf, opts->end_row, false, &oob);
|
||||
}
|
||||
|
||||
VALIDATE(!oob, "%s", "Line index out of bounds", {
|
||||
@ -534,27 +529,23 @@ Dictionary nvim_win_text_height(Window window, Dict(win_text_height) *opts, Aren
|
||||
return rv;
|
||||
});
|
||||
|
||||
if (HAS_KEY(opts->start_vcol)) {
|
||||
VALIDATE(HAS_KEY(opts->start_row), "%s", "'start_vcol' specified without 'start_row'", {
|
||||
if (HAS_KEY(opts, win_text_height, start_vcol)) {
|
||||
VALIDATE(HAS_KEY(opts, win_text_height, start_row),
|
||||
"%s", "'start_vcol' specified without 'start_row'", {
|
||||
return rv;
|
||||
});
|
||||
VALIDATE_T("start_vcol", kObjectTypeInteger, opts->start_vcol.type, {
|
||||
return rv;
|
||||
});
|
||||
start_vcol = opts->start_vcol.data.integer;
|
||||
start_vcol = opts->start_vcol;
|
||||
VALIDATE_RANGE((start_vcol >= 0 && start_vcol <= MAXCOL), "start_vcol", {
|
||||
return rv;
|
||||
});
|
||||
}
|
||||
|
||||
if (HAS_KEY(opts->end_vcol)) {
|
||||
VALIDATE(HAS_KEY(opts->end_row), "%s", "'end_vcol' specified without 'end_row'", {
|
||||
if (HAS_KEY(opts, win_text_height, end_vcol)) {
|
||||
VALIDATE(HAS_KEY(opts, win_text_height, end_row),
|
||||
"%s", "'end_vcol' specified without 'end_row'", {
|
||||
return rv;
|
||||
});
|
||||
VALIDATE_T("end_vcol", kObjectTypeInteger, opts->end_vcol.type, {
|
||||
return rv;
|
||||
});
|
||||
end_vcol = opts->end_vcol.data.integer;
|
||||
end_vcol = opts->end_vcol;
|
||||
VALIDATE_RANGE((end_vcol >= 0 && end_vcol <= MAXCOL), "end_vcol", {
|
||||
return rv;
|
||||
});
|
||||
@ -568,7 +559,7 @@ Dictionary nvim_win_text_height(Window window, Dict(win_text_height) *opts, Aren
|
||||
|
||||
int64_t fill = 0;
|
||||
int64_t all = win_text_height(win, start_lnum, start_vcol, end_lnum, end_vcol, &fill);
|
||||
if (!HAS_KEY(opts->end_row)) {
|
||||
if (!HAS_KEY(opts, win_text_height, end_row)) {
|
||||
const int64_t end_fill = win_get_fill(win, line_count + 1);
|
||||
fill += end_fill;
|
||||
all += end_fill;
|
||||
|
@ -271,8 +271,7 @@ static inline void ctx_save_funcs(Context *ctx, bool scriptonly)
|
||||
size_t cmd_len = sizeof("func! ") + strlen(name);
|
||||
char *cmd = xmalloc(cmd_len);
|
||||
snprintf(cmd, cmd_len, "func! %s", name);
|
||||
Dict(exec_opts) opts = { 0 };
|
||||
opts.output = BOOLEAN_OBJ(true);
|
||||
Dict(exec_opts) opts = { .output = true };
|
||||
String func_body = exec_impl(VIML_INTERNAL_CALL, cstr_as_string(cmd),
|
||||
&opts, &err);
|
||||
xfree(cmd);
|
||||
|
@ -67,13 +67,27 @@ local keysets = {}
|
||||
|
||||
local function add_keyset(val)
|
||||
local keys = {}
|
||||
for _,field in ipairs(val.fields) do
|
||||
local types = {}
|
||||
local is_set_name = 'is_set__' .. val.keyset_name .. '_'
|
||||
local has_optional = false
|
||||
for i,field in ipairs(val.fields) do
|
||||
if field.type ~= 'Object' then
|
||||
error 'not yet implemented: types other than Object'
|
||||
types[field.name] = field.type
|
||||
end
|
||||
if field.name ~= is_set_name and field.type ~= 'OptionalKeys' then
|
||||
table.insert(keys, field.name)
|
||||
else
|
||||
if i > 1 then
|
||||
error("'is_set__{type}_' must be first if present")
|
||||
elseif field.name ~= is_set_name then
|
||||
error(val.keyset_name..": name of first key should be "..is_set_name)
|
||||
elseif field.type ~= 'OptionalKeys' then
|
||||
error("'"..is_set_name.."' must have type 'OptionalKeys'")
|
||||
end
|
||||
has_optional = true
|
||||
end
|
||||
table.insert(keys, {field.name, field.type})
|
||||
end
|
||||
table.insert(keysets, {val.keyset_name, keys})
|
||||
table.insert(keysets, {name=val.keyset_name, keys=keys, types=types, has_optional=has_optional})
|
||||
end
|
||||
|
||||
-- read each input file, parse and append to the api metadata
|
||||
@ -232,53 +246,60 @@ output:write([[
|
||||
|
||||
]])
|
||||
|
||||
for _,keyset in ipairs(keysets) do
|
||||
local name, keys = unpack(keyset)
|
||||
local special = {}
|
||||
local function sanitize(key)
|
||||
if special[key] then
|
||||
return key .. "_"
|
||||
for _,k in ipairs(keysets) do
|
||||
local c_name = {}
|
||||
|
||||
for i = 1,#k.keys do
|
||||
-- some keys, like "register" are c keywords and get
|
||||
-- escaped with a trailing _ in the struct.
|
||||
if vim.endswith(k.keys[i], "_") then
|
||||
local orig = k.keys[i]
|
||||
k.keys[i] = string.sub(k.keys[i],1, #(k.keys[i]) - 1)
|
||||
c_name[k.keys[i]] = orig
|
||||
k.types[k.keys[i]] = k.types[orig]
|
||||
end
|
||||
return key
|
||||
end
|
||||
|
||||
local key_names = {}
|
||||
for i = 1,#keys do
|
||||
local kname = keys[i][1]
|
||||
if vim.endswith(kname, "_") then
|
||||
kname = string.sub(kname,1, #kname - 1)
|
||||
special[kname] = true
|
||||
end
|
||||
key_names[i] = kname
|
||||
end
|
||||
local neworder, hashfun = hashy.hashy_hash(name, key_names, function (idx)
|
||||
return name.."_table["..idx.."].str"
|
||||
local neworder, hashfun = hashy.hashy_hash(k.name, k.keys, function (idx)
|
||||
return k.name.."_table["..idx.."].str"
|
||||
end)
|
||||
|
||||
keysets_defs:write("extern KeySetLink "..name.."_table[];\n")
|
||||
keysets_defs:write("extern KeySetLink "..k.name.."_table[];\n")
|
||||
|
||||
output:write("KeySetLink "..name.."_table[] = {\n")
|
||||
for _, key in ipairs(neworder) do
|
||||
output:write(' {"'..key..'", offsetof(KeyDict_'..name..", "..sanitize(key)..")},\n")
|
||||
local function typename(type)
|
||||
if type ~= nil then
|
||||
return "kObjectType"..type
|
||||
else
|
||||
return "kObjectTypeNil"
|
||||
end
|
||||
end
|
||||
output:write(' {NULL, 0},\n')
|
||||
|
||||
output:write("KeySetLink "..k.name.."_table[] = {\n")
|
||||
for i, key in ipairs(neworder) do
|
||||
local ind = -1
|
||||
if k.has_optional then
|
||||
ind = i
|
||||
keysets_defs:write("#define KEYSET_OPTIDX_"..k.name.."__"..key.." "..ind.."\n")
|
||||
end
|
||||
output:write(' {"'..key..'", offsetof(KeyDict_'..k.name..", "..(c_name[key] or key).."), "..typename(k.types[key])..", "..ind.."},\n")
|
||||
end
|
||||
output:write(' {NULL, 0, kObjectTypeNil, -1},\n')
|
||||
output:write("};\n\n")
|
||||
|
||||
output:write(hashfun)
|
||||
|
||||
output:write([[
|
||||
Object *KeyDict_]]..name..[[_get_field(void *retval, const char *str, size_t len)
|
||||
KeySetLink *KeyDict_]]..k.name..[[_get_field(const char *str, size_t len)
|
||||
{
|
||||
int hash = ]]..name..[[_hash(str, len);
|
||||
int hash = ]]..k.name..[[_hash(str, len);
|
||||
if (hash == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (Object *)((char *)retval + ]]..name..[[_table[hash].ptr_off);
|
||||
return &]]..k.name..[[_table[hash];
|
||||
}
|
||||
|
||||
]])
|
||||
keysets_defs:write("#define api_free_keydict_"..name.."(x) api_free_keydict(x, "..name.."_table)\n")
|
||||
keysets_defs:write("#define api_free_keydict_"..k.name.."(x) api_free_keydict(x, "..k.name.."_table)\n")
|
||||
end
|
||||
|
||||
local function real_type(type)
|
||||
@ -558,6 +579,7 @@ local function process_function(fn)
|
||||
static int %s(lua_State *lstate)
|
||||
{
|
||||
Error err = ERROR_INIT;
|
||||
char *err_param = 0;
|
||||
if (lua_gettop(lstate) != %i) {
|
||||
api_set_error(&err, kErrorTypeValidation, "Expected %i argument%s");
|
||||
goto exit_0;
|
||||
@ -605,19 +627,22 @@ local function process_function(fn)
|
||||
extra = "true, "
|
||||
end
|
||||
local errshift = 0
|
||||
local seterr = ''
|
||||
if string.match(param_type, '^KeyDict_') then
|
||||
write_shifted_output(output, string.format([[
|
||||
%s %s = { 0 }; nlua_pop_keydict(lstate, &%s, %s_get_field, %s&err);]], param_type, cparam, cparam, param_type, extra))
|
||||
%s %s = { 0 }; nlua_pop_keydict(lstate, &%s, %s_get_field, &err_param, &err);]], param_type, cparam, cparam, param_type))
|
||||
cparam = '&'..cparam
|
||||
errshift = 1 -- free incomplete dict on error
|
||||
else
|
||||
write_shifted_output(output, string.format([[
|
||||
const %s %s = nlua_pop_%s(lstate, %s&err);]], param[1], cparam, param_type, extra))
|
||||
seterr = [[
|
||||
err_param = "]]..param[2]..[[";]]
|
||||
end
|
||||
|
||||
write_shifted_output(output, string.format([[
|
||||
|
||||
if (ERROR_SET(&err)) {
|
||||
if (ERROR_SET(&err)) {]]..seterr..[[
|
||||
goto exit_%u;
|
||||
}
|
||||
|
||||
@ -661,9 +686,14 @@ local function process_function(fn)
|
||||
exit_0:
|
||||
if (ERROR_SET(&err)) {
|
||||
luaL_where(lstate, 1);
|
||||
if (err_param) {
|
||||
lua_pushstring(lstate, "Invalid '");
|
||||
lua_pushstring(lstate, err_param);
|
||||
lua_pushstring(lstate, "': ");
|
||||
}
|
||||
lua_pushstring(lstate, err.msg);
|
||||
api_clear_error(&err);
|
||||
lua_concat(lstate, 2);
|
||||
lua_concat(lstate, err_param ? 5 : 2);
|
||||
return lua_error(lstate);
|
||||
}
|
||||
]]
|
||||
|
@ -226,8 +226,8 @@ int ns_get_hl(NS *ns_hl, int hl_id, bool link, bool nodefault)
|
||||
if (api_dict_to_keydict(&dict, KeyDict_highlight_get_field,
|
||||
ret.data.dictionary, &err)) {
|
||||
attrs = dict2hlattrs(&dict, true, &it.link_id, &err);
|
||||
fallback = api_object_to_bool(dict.fallback, "fallback", true, &err);
|
||||
tmp = api_object_to_bool(dict.fallback, "tmp", false, &err);
|
||||
fallback = GET_BOOL_OR_TRUE(&dict, highlight, fallback);
|
||||
tmp = dict.fallback; // or false
|
||||
if (it.link_id >= 0) {
|
||||
fallback = true;
|
||||
}
|
||||
@ -938,6 +938,7 @@ void hlattrs2dict(Dictionary *hl, Dictionary *hl_attrs, HlAttrs ae, bool use_rgb
|
||||
|
||||
HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *err)
|
||||
{
|
||||
#define HAS_KEY_X(d, key) HAS_KEY(d, highlight, key)
|
||||
HlAttrs hlattrs = HLATTRS_INIT;
|
||||
int32_t fg = -1, bg = -1, ctermfg = -1, ctermbg = -1, sp = -1;
|
||||
int blend = -1;
|
||||
@ -946,7 +947,7 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
|
||||
bool cterm_mask_provided = false;
|
||||
|
||||
#define CHECK_FLAG(d, m, name, extra, flag) \
|
||||
if (api_object_to_bool(d->name##extra, #name, false, err)) { \
|
||||
if (d->name##extra) { \
|
||||
if (flag & HL_UNDERLINE_MASK) { \
|
||||
m &= ~HL_UNDERLINE_MASK; \
|
||||
} \
|
||||
@ -971,52 +972,48 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
|
||||
CHECK_FLAG(dict, mask, nocombine, , HL_NOCOMBINE);
|
||||
CHECK_FLAG(dict, mask, default, _, HL_DEFAULT);
|
||||
|
||||
if (HAS_KEY(dict->fg)) {
|
||||
if (HAS_KEY_X(dict, fg)) {
|
||||
fg = object_to_color(dict->fg, "fg", use_rgb, err);
|
||||
} else if (HAS_KEY(dict->foreground)) {
|
||||
} else if (HAS_KEY_X(dict, foreground)) {
|
||||
fg = object_to_color(dict->foreground, "foreground", use_rgb, err);
|
||||
}
|
||||
if (ERROR_SET(err)) {
|
||||
return hlattrs;
|
||||
}
|
||||
|
||||
if (HAS_KEY(dict->bg)) {
|
||||
if (HAS_KEY_X(dict, bg)) {
|
||||
bg = object_to_color(dict->bg, "bg", use_rgb, err);
|
||||
} else if (HAS_KEY(dict->background)) {
|
||||
} else if (HAS_KEY_X(dict, background)) {
|
||||
bg = object_to_color(dict->background, "background", use_rgb, err);
|
||||
}
|
||||
if (ERROR_SET(err)) {
|
||||
return hlattrs;
|
||||
}
|
||||
|
||||
if (HAS_KEY(dict->sp)) {
|
||||
if (HAS_KEY_X(dict, sp)) {
|
||||
sp = object_to_color(dict->sp, "sp", true, err);
|
||||
} else if (HAS_KEY(dict->special)) {
|
||||
} else if (HAS_KEY_X(dict, special)) {
|
||||
sp = object_to_color(dict->special, "special", true, err);
|
||||
}
|
||||
if (ERROR_SET(err)) {
|
||||
return hlattrs;
|
||||
}
|
||||
|
||||
if (HAS_KEY(dict->blend)) {
|
||||
VALIDATE_T("blend", kObjectTypeInteger, dict->blend.type, {
|
||||
return hlattrs;
|
||||
});
|
||||
|
||||
Integer blend0 = dict->blend.data.integer;
|
||||
if (HAS_KEY_X(dict, blend)) {
|
||||
Integer blend0 = dict->blend;
|
||||
VALIDATE_RANGE((blend0 >= 0 && blend0 <= 100), "blend", {
|
||||
return hlattrs;
|
||||
});
|
||||
blend = (int)blend0;
|
||||
}
|
||||
|
||||
if (HAS_KEY(dict->link) || HAS_KEY(dict->global_link)) {
|
||||
if (HAS_KEY_X(dict, link) || HAS_KEY_X(dict, global_link)) {
|
||||
if (!link_id) {
|
||||
api_set_error(err, kErrorTypeValidation, "Invalid Key: '%s'",
|
||||
HAS_KEY(dict->global_link) ? "global_link" : "link");
|
||||
HAS_KEY_X(dict, global_link) ? "global_link" : "link");
|
||||
return hlattrs;
|
||||
}
|
||||
if (HAS_KEY(dict->global_link)) {
|
||||
if (HAS_KEY_X(dict, global_link)) {
|
||||
*link_id = object_to_hl_id(dict->global_link, "link", err);
|
||||
mask |= HL_GLOBAL;
|
||||
} else {
|
||||
@ -1050,21 +1047,21 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
|
||||
// empty list from Lua API should clear all cterm attributes
|
||||
// TODO(clason): handle via gen_api_dispatch
|
||||
cterm_mask_provided = true;
|
||||
} else if (HAS_KEY(dict->cterm)) {
|
||||
} else if (HAS_KEY_X(dict, cterm)) {
|
||||
VALIDATE_EXP(false, "cterm", "Dict", api_typename(dict->cterm.type), {
|
||||
return hlattrs;
|
||||
});
|
||||
}
|
||||
#undef CHECK_FLAG
|
||||
|
||||
if (HAS_KEY(dict->ctermfg)) {
|
||||
if (HAS_KEY_X(dict, ctermfg)) {
|
||||
ctermfg = object_to_color(dict->ctermfg, "ctermfg", false, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return hlattrs;
|
||||
}
|
||||
}
|
||||
|
||||
if (HAS_KEY(dict->ctermbg)) {
|
||||
if (HAS_KEY_X(dict, ctermbg)) {
|
||||
ctermbg = object_to_color(dict->ctermbg, "ctermbg", false, err);
|
||||
if (ERROR_SET(err)) {
|
||||
return hlattrs;
|
||||
@ -1091,6 +1088,7 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
|
||||
}
|
||||
|
||||
return hlattrs;
|
||||
#undef HAS_KEY_X
|
||||
}
|
||||
|
||||
int object_to_color(Object val, char *key, bool rgb, Error *err)
|
||||
|
@ -832,9 +832,11 @@ void set_hl_group(int id, HlAttrs attrs, Dict(highlight) *dict, int link_id)
|
||||
struct {
|
||||
int *dest; RgbValue val; Object name;
|
||||
} cattrs[] = {
|
||||
{ &g->sg_rgb_fg_idx, g->sg_rgb_fg, HAS_KEY(dict->fg) ? dict->fg : dict->foreground },
|
||||
{ &g->sg_rgb_bg_idx, g->sg_rgb_bg, HAS_KEY(dict->bg) ? dict->bg : dict->background },
|
||||
{ &g->sg_rgb_sp_idx, g->sg_rgb_sp, HAS_KEY(dict->sp) ? dict->sp : dict->special },
|
||||
{ &g->sg_rgb_fg_idx, g->sg_rgb_fg,
|
||||
HAS_KEY(dict, highlight, fg) ? dict->fg : dict->foreground },
|
||||
{ &g->sg_rgb_bg_idx, g->sg_rgb_bg,
|
||||
HAS_KEY(dict, highlight, bg) ? dict->bg : dict->background },
|
||||
{ &g->sg_rgb_sp_idx, g->sg_rgb_sp, HAS_KEY(dict, highlight, sp) ? dict->sp : dict->special },
|
||||
{ NULL, -1, NIL },
|
||||
};
|
||||
|
||||
@ -1563,19 +1565,12 @@ static bool hlgroup2dict(Dictionary *hl, NS ns_id, int hl_id, Arena *arena)
|
||||
|
||||
Dictionary ns_get_hl_defs(NS ns_id, Dict(get_highlight) *opts, Arena *arena, Error *err)
|
||||
{
|
||||
Boolean link = api_object_to_bool(opts->link, "link", true, err);
|
||||
Boolean link = GET_BOOL_OR_TRUE(opts, get_highlight, link);
|
||||
int id = -1;
|
||||
if (opts->name.type != kObjectTypeNil) {
|
||||
VALIDATE_T("highlight name", kObjectTypeString, opts->name.type, {
|
||||
goto cleanup;
|
||||
});
|
||||
String name = opts->name.data.string;
|
||||
id = syn_check_group(name.data, name.size);
|
||||
} else if (opts->id.type != kObjectTypeNil) {
|
||||
VALIDATE_T("highlight id", kObjectTypeInteger, opts->id.type, {
|
||||
goto cleanup;
|
||||
});
|
||||
id = (int)opts->id.data.integer;
|
||||
if (HAS_KEY(opts, get_highlight, name)) {
|
||||
id = syn_check_group(opts->name.data, opts->name.size);
|
||||
} else if (HAS_KEY(opts, get_highlight, id)) {
|
||||
id = (int)opts->id;
|
||||
}
|
||||
|
||||
if (id != -1) {
|
||||
|
@ -813,7 +813,7 @@ String nlua_pop_String(lua_State *lstate, Error *err)
|
||||
{
|
||||
if (lua_type(lstate, -1) != LUA_TSTRING) {
|
||||
lua_pop(lstate, 1);
|
||||
api_set_error(err, kErrorTypeValidation, "Expected lua string");
|
||||
api_set_error(err, kErrorTypeValidation, "Expected Lua string");
|
||||
return (String) { .size = 0, .data = NULL };
|
||||
}
|
||||
String ret;
|
||||
@ -834,7 +834,7 @@ Integer nlua_pop_Integer(lua_State *lstate, Error *err)
|
||||
{
|
||||
if (lua_type(lstate, -1) != LUA_TNUMBER) {
|
||||
lua_pop(lstate, 1);
|
||||
api_set_error(err, kErrorTypeValidation, "Expected lua number");
|
||||
api_set_error(err, kErrorTypeValidation, "Expected Lua number");
|
||||
return 0;
|
||||
}
|
||||
const lua_Number n = lua_tonumber(lstate, -1);
|
||||
@ -871,7 +871,8 @@ static inline LuaTableProps nlua_check_type(lua_State *const lstate, Error *cons
|
||||
{
|
||||
if (lua_type(lstate, -1) != LUA_TTABLE) {
|
||||
if (err) {
|
||||
api_set_error(err, kErrorTypeValidation, "Expected lua table");
|
||||
api_set_error(err, kErrorTypeValidation, "Expected Lua %s",
|
||||
(type == kObjectTypeFloat) ? "number" : "table");
|
||||
}
|
||||
return (LuaTableProps) { .type = kObjectTypeNil };
|
||||
}
|
||||
@ -884,7 +885,7 @@ static inline LuaTableProps nlua_check_type(lua_State *const lstate, Error *cons
|
||||
|
||||
if (table_props.type != type) {
|
||||
if (err) {
|
||||
api_set_error(err, kErrorTypeValidation, "Unexpected type");
|
||||
api_set_error(err, kErrorTypeValidation, "Expected %s-like Lua table", api_typename(type));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1168,7 +1169,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
|
||||
break;
|
||||
case kObjectTypeNil:
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"Cannot convert given lua table");
|
||||
"Cannot convert given Lua table");
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
@ -1224,26 +1225,19 @@ LuaRef nlua_pop_LuaRef(lua_State *const lstate, Error *err)
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define GENERATE_INDEX_FUNCTION(type) \
|
||||
type nlua_pop_##type(lua_State *lstate, Error *err) \
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT \
|
||||
{ \
|
||||
type ret; \
|
||||
if (lua_type(lstate, -1) != LUA_TNUMBER) { \
|
||||
api_set_error(err, kErrorTypeValidation, "Expected Lua number"); \
|
||||
ret = (type) - 1; \
|
||||
} else { \
|
||||
ret = (type)lua_tonumber(lstate, -1); \
|
||||
} \
|
||||
lua_pop(lstate, 1); \
|
||||
return ret; \
|
||||
handle_T nlua_pop_handle(lua_State *lstate, Error *err)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
handle_T ret;
|
||||
if (lua_type(lstate, -1) != LUA_TNUMBER) {
|
||||
api_set_error(err, kErrorTypeValidation, "Expected Lua number");
|
||||
ret = (handle_T) - 1;
|
||||
} else {
|
||||
ret = (handle_T)lua_tonumber(lstate, -1);
|
||||
}
|
||||
|
||||
GENERATE_INDEX_FUNCTION(Buffer)
|
||||
GENERATE_INDEX_FUNCTION(Window)
|
||||
GENERATE_INDEX_FUNCTION(Tabpage)
|
||||
|
||||
#undef GENERATE_INDEX_FUNCTION
|
||||
lua_pop(lstate, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Record some auxiliary values in vim module
|
||||
///
|
||||
@ -1292,10 +1286,11 @@ void nlua_init_types(lua_State *const lstate)
|
||||
lua_rawset(lstate, -3);
|
||||
}
|
||||
|
||||
void nlua_pop_keydict(lua_State *L, void *retval, field_hash hashy, Error *err)
|
||||
// lua specific variant of api_dict_to_keydict
|
||||
void nlua_pop_keydict(lua_State *L, void *retval, FieldHashfn hashy, char **err_opt, Error *err)
|
||||
{
|
||||
if (!lua_istable(L, -1)) {
|
||||
api_set_error(err, kErrorTypeValidation, "Expected lua table");
|
||||
api_set_error(err, kErrorTypeValidation, "Expected Lua table");
|
||||
lua_pop(L, -1);
|
||||
return;
|
||||
}
|
||||
@ -1305,14 +1300,45 @@ void nlua_pop_keydict(lua_State *L, void *retval, field_hash hashy, Error *err)
|
||||
// [dict, key, value]
|
||||
size_t len;
|
||||
const char *s = lua_tolstring(L, -2, &len);
|
||||
Object *field = hashy(retval, s, len);
|
||||
KeySetLink *field = hashy(s, len);
|
||||
if (!field) {
|
||||
api_set_error(err, kErrorTypeValidation, "invalid key: %.*s", (int)len, s);
|
||||
lua_pop(L, 3); // []
|
||||
return;
|
||||
}
|
||||
|
||||
*field = nlua_pop_Object(L, true, err);
|
||||
if (field->opt_index >= 0) {
|
||||
OptKeySet *ks = (OptKeySet *)retval;
|
||||
ks->is_set_ |= (1ULL << field->opt_index);
|
||||
}
|
||||
char *mem = ((char *)retval + field->ptr_off);
|
||||
|
||||
if (field->type == kObjectTypeNil) {
|
||||
*(Object *)mem = nlua_pop_Object(L, true, err);
|
||||
} else if (field->type == kObjectTypeInteger) {
|
||||
*(Integer *)mem = nlua_pop_Integer(L, err);
|
||||
} else if (field->type == kObjectTypeBoolean) {
|
||||
*(Boolean *)mem = nlua_pop_Boolean(L, err);
|
||||
} else if (field->type == kObjectTypeString) {
|
||||
*(String *)mem = nlua_pop_String(L, err);
|
||||
} else if (field->type == kObjectTypeFloat) {
|
||||
*(Float *)mem = nlua_pop_Float(L, err);
|
||||
} else if (field->type == kObjectTypeBuffer || field->type == kObjectTypeWindow
|
||||
|| field->type == kObjectTypeTabpage) {
|
||||
*(handle_T *)mem = nlua_pop_handle(L, err);
|
||||
} else if (field->type == kObjectTypeArray) {
|
||||
*(Array *)mem = nlua_pop_Array(L, err);
|
||||
} else if (field->type == kObjectTypeDictionary) {
|
||||
*(Dictionary *)mem = nlua_pop_Dictionary(L, false, err);
|
||||
} else if (field->type == kObjectTypeLuaRef) {
|
||||
*(LuaRef *)mem = nlua_pop_LuaRef(L, err);
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
if (ERROR_SET(err)) {
|
||||
*err_opt = field->str;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// [dict]
|
||||
lua_pop(L, 1);
|
||||
|
@ -9,6 +9,10 @@
|
||||
#include "nvim/eval/typval_defs.h"
|
||||
#include "nvim/func_attr.h"
|
||||
|
||||
#define nlua_pop_Buffer nlua_pop_handle
|
||||
#define nlua_pop_Window nlua_pop_handle
|
||||
#define nlua_pop_Tabpage nlua_pop_handle
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "lua/converter.h.generated.h"
|
||||
#endif
|
||||
|
@ -2558,26 +2558,22 @@ void modify_keymap(uint64_t channel_id, Buffer buffer, bool is_unmap, String mod
|
||||
|
||||
const sctx_T save_current_sctx = api_set_sctx(channel_id);
|
||||
|
||||
if (opts != NULL && opts->callback.type == kObjectTypeLuaRef) {
|
||||
lua_funcref = opts->callback.data.luaref;
|
||||
opts->callback.data.luaref = LUA_NOREF;
|
||||
}
|
||||
MapArguments parsed_args = MAP_ARGUMENTS_INIT;
|
||||
if (opts) {
|
||||
#define KEY_TO_BOOL(name) \
|
||||
parsed_args.name = api_object_to_bool(opts->name, #name, false, err); \
|
||||
if (ERROR_SET(err)) { \
|
||||
goto fail_and_free; \
|
||||
}
|
||||
|
||||
KEY_TO_BOOL(nowait);
|
||||
KEY_TO_BOOL(noremap);
|
||||
KEY_TO_BOOL(silent);
|
||||
KEY_TO_BOOL(script);
|
||||
KEY_TO_BOOL(expr);
|
||||
KEY_TO_BOOL(unique);
|
||||
KEY_TO_BOOL(replace_keycodes);
|
||||
#undef KEY_TO_BOOL
|
||||
parsed_args.nowait = opts->nowait;
|
||||
parsed_args.noremap = opts->noremap;
|
||||
parsed_args.silent = opts->silent;
|
||||
parsed_args.script = opts->script;
|
||||
parsed_args.expr = opts->expr;
|
||||
parsed_args.unique = opts->unique;
|
||||
parsed_args.replace_keycodes = opts->replace_keycodes;
|
||||
if (HAS_KEY(opts, keymap, callback)) {
|
||||
lua_funcref = opts->callback;
|
||||
opts->callback = LUA_NOREF;
|
||||
}
|
||||
if (HAS_KEY(opts, keymap, desc)) {
|
||||
parsed_args.desc = string_to_cstr(opts->desc);
|
||||
}
|
||||
}
|
||||
parsed_args.buffer = !global;
|
||||
|
||||
@ -2593,11 +2589,6 @@ void modify_keymap(uint64_t channel_id, Buffer buffer, bool is_unmap, String mod
|
||||
goto fail_and_free;
|
||||
}
|
||||
|
||||
if (opts != NULL && opts->desc.type == kObjectTypeString) {
|
||||
parsed_args.desc = string_to_cstr(opts->desc.data.string);
|
||||
} else {
|
||||
parsed_args.desc = NULL;
|
||||
}
|
||||
if (parsed_args.lhs_len > MAXMAPLEN || parsed_args.alt_lhs_len > MAXMAPLEN) {
|
||||
api_set_error(err, kErrorTypeValidation, "LHS exceeds maximum map length: %s", lhs.data);
|
||||
goto fail_and_free;
|
||||
|
@ -737,7 +737,7 @@ describe('autocmd api', function()
|
||||
eq("Invalid 'group': 0", pcall_err(meths.exec_autocmds, 'FileType', {
|
||||
group = 0,
|
||||
}))
|
||||
eq("Invalid 'buffer': expected Integer, got Array", pcall_err(meths.exec_autocmds, 'FileType', {
|
||||
eq("Invalid 'buffer': expected Buffer, got Array", pcall_err(meths.exec_autocmds, 'FileType', {
|
||||
buffer = {},
|
||||
}))
|
||||
eq("Invalid 'event' item: expected String, got Array", pcall_err(meths.exec_autocmds,
|
||||
|
@ -109,7 +109,7 @@ describe('API/extmarks', function()
|
||||
eq("Invalid 'virt_text_pos': 'foo'", pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 'foo' }))
|
||||
eq("Invalid 'hl_mode': expected String, got Integer", pcall_err(set_extmark, ns, marks[2], 0, 0, { hl_mode = 0 }))
|
||||
eq("Invalid 'hl_mode': 'foo'", pcall_err(set_extmark, ns, marks[2], 0, 0, { hl_mode = 'foo' }))
|
||||
eq("Invalid 'id': expected positive Integer", pcall_err(set_extmark, ns, {}, 0, 0, { end_col = 1, end_row = 1 }))
|
||||
eq("Invalid 'id': expected Integer, got Array", pcall_err(set_extmark, ns, {}, 0, 0, { end_col = 1, end_row = 1 }))
|
||||
eq("Invalid mark position: expected 2 Integer items", pcall_err(get_extmarks, ns, {}, {-1, -1}))
|
||||
eq("Invalid mark position: expected mark id Integer or 2-item Array", pcall_err(get_extmarks, ns, true, {-1, -1}))
|
||||
-- No memory leak with virt_text, virt_lines, sign_text
|
||||
|
@ -434,10 +434,8 @@ describe('API: get highlight', function()
|
||||
before_each(clear)
|
||||
|
||||
it('validation', function()
|
||||
eq(
|
||||
'Invalid highlight name: expected String, got Integer',
|
||||
pcall_err(meths.get_hl, 0, { name = 177 })
|
||||
)
|
||||
eq("Invalid 'name': expected String, got Integer",
|
||||
pcall_err(meths.get_hl, 0, { name = 177 }))
|
||||
eq('Highlight id out of bounds', pcall_err(meths.get_hl, 0, { name = 'Test set hl' }))
|
||||
end)
|
||||
|
||||
@ -534,7 +532,7 @@ describe('API: get highlight', function()
|
||||
eq('Highlight id out of bounds', pcall_err(meths.get_hl, 0, { id = 0 }))
|
||||
|
||||
eq(
|
||||
'Invalid highlight id: expected Integer, got String',
|
||||
"Invalid 'id': expected Integer, got String",
|
||||
pcall_err(meths.get_hl, 0, { id = 'Test_set_hl' })
|
||||
)
|
||||
|
||||
|
@ -4112,12 +4112,10 @@ describe('API', function()
|
||||
it('validation', function()
|
||||
eq("Invalid 'cmd': expected non-empty String",
|
||||
pcall_err(meths.cmd, { cmd = ""}, {}))
|
||||
eq("Invalid 'cmd': expected non-empty String",
|
||||
eq("Invalid 'cmd': expected String, got Array",
|
||||
pcall_err(meths.cmd, { cmd = {}}, {}))
|
||||
eq("Invalid 'args': expected Array, got Boolean",
|
||||
pcall_err(meths.cmd, { cmd = "set", args = true }, {}))
|
||||
eq("Invalid 'magic': expected Dict, got Array",
|
||||
pcall_err(meths.cmd, { cmd = "set", args = {}, magic = {} }, {}))
|
||||
eq("Invalid command arg: expected non-whitespace",
|
||||
pcall_err(meths.cmd, { cmd = "set", args = {' '}, }, {}))
|
||||
eq("Invalid command arg: expected valid type, got Array",
|
||||
@ -4138,7 +4136,7 @@ describe('API', function()
|
||||
|
||||
eq("Command cannot accept count: set",
|
||||
pcall_err(meths.cmd, { cmd = "set", args = {}, count = 1 }, {}))
|
||||
eq("Invalid 'count': expected non-negative Integer",
|
||||
eq("Invalid 'count': expected Integer, got Boolean",
|
||||
pcall_err(meths.cmd, { cmd = "print", args = {}, count = true }, {}))
|
||||
eq("Invalid 'count': expected non-negative Integer",
|
||||
pcall_err(meths.cmd, { cmd = "print", args = {}, count = -1 }, {}))
|
||||
@ -4158,9 +4156,10 @@ describe('API', function()
|
||||
-- Lua call allows empty {} for dict item.
|
||||
eq('', exec_lua([[return vim.cmd{ cmd = "set", args = {}, magic = {} }]]))
|
||||
eq('', exec_lua([[return vim.cmd{ cmd = "set", args = {}, mods = {} }]]))
|
||||
eq('', meths.cmd({ cmd = "set", args = {}, magic = {} }, {}))
|
||||
|
||||
-- Lua call does not allow non-empty list-like {} for dict item.
|
||||
eq("Invalid 'magic': expected Dict, got Array",
|
||||
eq("Invalid 'magic': Expected Dict-like Lua table",
|
||||
pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, magic = { 'a' } }]]))
|
||||
eq("Invalid key: 'bogus'",
|
||||
pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, magic = { bogus = true } }]]))
|
||||
|
@ -173,7 +173,7 @@ describe('luaeval(vim.api.…)', function()
|
||||
|
||||
it('errors out correctly when working with API', function()
|
||||
-- Conversion errors
|
||||
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Cannot convert given lua table',
|
||||
eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'obj': Cannot convert given Lua table]],
|
||||
remove_trace(exc_exec([[call luaeval("vim.api.nvim__id({1, foo=42})")]])))
|
||||
-- Errors in number of arguments
|
||||
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 1 argument',
|
||||
@ -183,32 +183,32 @@ describe('luaeval(vim.api.…)', function()
|
||||
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 2 arguments',
|
||||
remove_trace(exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2, 3)")]])))
|
||||
-- Error in argument types
|
||||
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua string',
|
||||
eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'name': Expected Lua string]],
|
||||
remove_trace(exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2)")]])))
|
||||
|
||||
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua number',
|
||||
eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'start': Expected Lua number]],
|
||||
remove_trace(exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 'test', 1, false)")]])))
|
||||
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Number is not integral',
|
||||
eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'start': Number is not integral]],
|
||||
remove_trace(exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 1.5, 1, false)")]])))
|
||||
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected Lua number',
|
||||
eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'window': Expected Lua number]],
|
||||
remove_trace(exc_exec([[call luaeval("vim.api.nvim_win_is_valid(nil)")]])))
|
||||
|
||||
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table',
|
||||
eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'flt': Expected Lua number]],
|
||||
remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_float('test')")]])))
|
||||
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Unexpected type',
|
||||
eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'flt': Expected Float-like Lua table]],
|
||||
remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_float({[vim.type_idx]=vim.types.dictionary})")]])))
|
||||
|
||||
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table',
|
||||
eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'arr': Expected Lua table]],
|
||||
remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_array(1)")]])))
|
||||
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Unexpected type',
|
||||
eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'arr': Expected Array-like Lua table]],
|
||||
remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_array({[vim.type_idx]=vim.types.dictionary})")]])))
|
||||
|
||||
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table',
|
||||
eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'dct': Expected Lua table]],
|
||||
remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_dictionary(1)")]])))
|
||||
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Unexpected type',
|
||||
eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'dct': Expected Dict-like Lua table]],
|
||||
remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.array})")]])))
|
||||
|
||||
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table',
|
||||
eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected Lua table]],
|
||||
remove_trace(exc_exec([[call luaeval("vim.api.nvim_set_keymap('', '', '', '')")]])))
|
||||
|
||||
-- TODO: check for errors with Tabpage argument
|
||||
|
@ -1511,7 +1511,7 @@ describe('lua stdlib', function()
|
||||
eq(true, funcs.luaeval "vim.bo[BUF].modifiable")
|
||||
matches("Unknown option 'nosuchopt'$",
|
||||
pcall_err(exec_lua, 'return vim.bo.nosuchopt'))
|
||||
matches("Expected lua string$",
|
||||
matches("Expected Lua string$",
|
||||
pcall_err(exec_lua, 'return vim.bo[0][0].autoread'))
|
||||
matches("Invalid buffer id: %-1$",
|
||||
pcall_err(exec_lua, 'return vim.bo[-1].filetype'))
|
||||
|
Loading…
Reference in New Issue
Block a user