aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/vim.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/api/vim.c')
-rw-r--r--src/nvim/api/vim.c171
1 files changed, 129 insertions, 42 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index f81cdf9deb..9d0b096a36 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -19,6 +19,7 @@
#include "nvim/ascii.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
+#include "nvim/charset.h"
#include "nvim/context.h"
#include "nvim/decoration.h"
#include "nvim/edit.h"
@@ -30,7 +31,9 @@
#include "nvim/file_search.h"
#include "nvim/fileio.h"
#include "nvim/getchar.h"
+#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/lua/executor.h"
#include "nvim/mark.h"
#include "nvim/memline.h"
@@ -121,7 +124,13 @@ Dictionary nvim__get_hl_defs(Integer ns_id, Error *err)
/// Set a highlight group.
///
-/// @param ns_id number of namespace for this highlight
+/// Note: unlike the `:highlight` command which can update a highlight group,
+/// this function completely replaces the definition. For example:
+/// `nvim_set_hl(0, 'Visual', {})` will clear the highlight group 'Visual'.
+///
+/// @param ns_id number of namespace for this highlight. Use value 0
+/// to set a highlight group in the global (`:highlight`)
+/// namespace.
/// @param name highlight group name, like ErrorMsg
/// @param val highlight definition map, like |nvim_get_hl_by_name|.
/// in addition the following keys are also recognized:
@@ -135,9 +144,8 @@ Dictionary nvim__get_hl_defs(Integer ns_id, Error *err)
/// same as attributes of gui color
/// @param[out] err Error details, if any
///
-/// TODO: ns_id = 0, should modify :highlight namespace
-/// TODO val should take update vs reset flag
-void nvim_set_hl(Integer ns_id, String name, Dictionary val, Error *err)
+// TODO(bfredl): val should take update vs reset flag
+void nvim_set_hl(Integer ns_id, String name, Dict(highlight) *val, Error *err)
FUNC_API_SINCE(7)
{
int hl_id = syn_check_group(name.data, (int)name.size);
@@ -145,7 +153,7 @@ void nvim_set_hl(Integer ns_id, String name, Dictionary val, Error *err)
HlAttrs attrs = dict2hlattrs(val, true, &link_id, err);
if (!ERROR_SET(err)) {
- ns_hl_def((NS)ns_id, hl_id, attrs, link_id);
+ ns_hl_def((NS)ns_id, hl_id, attrs, link_id, val);
}
}
@@ -169,7 +177,7 @@ void nvim__set_hl_ns(Integer ns_id, Error *err)
// event path for redraws caused by "fast" events. This could tie in with
// better throttling of async events causing redraws, such as non-batched
// nvim_buf_set_extmark calls from async contexts.
- if (!provider_active && !ns_hl_changed) {
+ if (!provider_active && !ns_hl_changed && must_redraw < NOT_VALID) {
multiqueue_put(main_loop.events, on_redraw_event, 0);
}
ns_hl_changed = true;
@@ -187,21 +195,23 @@ static void on_redraw_event(void **argv)
/// On execution error: does not fail, but updates v:errmsg.
///
/// To input sequences like <C-o> use |nvim_replace_termcodes()| (typically
-/// with escape_csi=true) to replace |keycodes|, then pass the result to
+/// with escape_ks=false) to replace |keycodes|, then pass the result to
/// nvim_feedkeys().
///
/// Example:
/// <pre>
/// :let key = nvim_replace_termcodes("<C-o>", v:true, v:false, v:true)
-/// :call nvim_feedkeys(key, 'n', v:true)
+/// :call nvim_feedkeys(key, 'n', v:false)
/// </pre>
///
/// @param keys to be typed
/// @param mode behavior flags, see |feedkeys()|
-/// @param escape_csi If true, escape K_SPECIAL/CSI bytes in `keys`
+/// @param escape_ks If true, escape K_SPECIAL bytes in `keys`
+/// This should be false if you already used
+/// |nvim_replace_termcodes()|, and true otherwise.
/// @see feedkeys()
-/// @see vim_strsave_escape_csi
-void nvim_feedkeys(String keys, String mode, Boolean escape_csi)
+/// @see vim_strsave_escape_ks
+void nvim_feedkeys(String keys, String mode, Boolean escape_ks)
FUNC_API_SINCE(1)
{
bool remap = true;
@@ -232,10 +242,10 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi)
}
char *keys_esc;
- if (escape_csi) {
- // Need to escape K_SPECIAL and CSI before putting the string in the
+ if (escape_ks) {
+ // Need to escape K_SPECIAL before putting the string in the
// typeahead buffer.
- keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data);
+ keys_esc = (char *)vim_strsave_escape_ks((char_u *)keys.data);
} else {
keys_esc = keys.data;
}
@@ -245,7 +255,7 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi)
typebuf_was_filled = true;
}
- if (escape_csi) {
+ if (escape_ks) {
xfree(keys_esc);
}
@@ -383,7 +393,7 @@ error:
/// @param str String to be converted.
/// @param from_part Legacy Vim parameter. Usually true.
/// @param do_lt Also translate <lt>. Ignored if `special` is false.
-/// @param special Replace |keycodes|, e.g. <CR> becomes a "\n" char.
+/// @param special Replace |keycodes|, e.g. <CR> becomes a "\r" char.
/// @see replace_termcodes
/// @see cpoptions
String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Boolean special)
@@ -491,8 +501,12 @@ ArrayOf(String) nvim_get_runtime_file(String name, Boolean all, Error *err)
int flags = DIP_DIRFILE | (all ? DIP_ALL : 0);
- do_in_runtimepath((char_u *)(name.size ? name.data : ""),
- flags, find_runtime_cb, &rv);
+ TRY_WRAP({
+ try_start();
+ do_in_runtimepath((char_u *)(name.size ? name.data : ""),
+ flags, find_runtime_cb, &rv);
+ try_end(err);
+ });
return rv;
}
@@ -540,20 +554,19 @@ void nvim_set_current_dir(String dir, Error *err)
return;
}
- char string[MAXPATHL];
+ char_u string[MAXPATHL];
memcpy(string, dir.data, dir.size);
string[dir.size] = NUL;
try_start();
- if (vim_chdir((char_u *)string)) {
+ if (!changedir_func(string, kCdScopeGlobal)) {
if (!try_end(err)) {
api_set_error(err, kErrorTypeException, "Failed to change directory");
}
return;
}
- post_chdir(kCdScopeGlobal, true);
try_end(err);
}
@@ -596,7 +609,19 @@ void nvim_del_current_line(Error *err)
Object nvim_get_var(String name, Error *err)
FUNC_API_SINCE(1)
{
- return dict_get_value(&globvardict, name, err);
+ dictitem_T *di = tv_dict_find(&globvardict, name.data, (ptrdiff_t)name.size);
+ if (di == NULL) { // try to autoload script
+ if (!script_autoload(name.data, name.size, false) || aborting()) {
+ api_set_error(err, kErrorTypeValidation, "Key not found: %s", name.data);
+ return (Object)OBJECT_INIT;
+ }
+ di = tv_dict_find(&globvardict, name.data, (ptrdiff_t)name.size);
+ }
+ if (di == NULL) {
+ api_set_error(err, kErrorTypeValidation, "Key not found: %s", name.data);
+ return (Object)OBJECT_INIT;
+ }
+ return vim_to_object(&di->di_tv);
}
/// Sets a global (g:) variable.
@@ -662,7 +687,7 @@ Object nvim_get_option(String name, Error *err)
///
/// @param name Option name
/// @param opts Optional parameters
-/// - scope: One of 'global' or 'local'. Analagous to
+/// - scope: One of 'global' or 'local'. Analogous to
/// |:setglobal| and |:setlocal|, respectively.
/// @param[out] err Error details, if any
/// @return Option value
@@ -724,7 +749,7 @@ end:
/// @param name Option name
/// @param value New option value
/// @param opts Optional parameters
-/// - scope: One of 'global' or 'local'. Analagous to
+/// - scope: One of 'global' or 'local'. Analogous to
/// |:setglobal| and |:setlocal|, respectively.
/// @param[out] err Error details, if any
void nvim_set_option_value(String name, Object value, Dict(option) *opts, Error *err)
@@ -1163,7 +1188,7 @@ static void term_close(void *data)
/// Send data to channel `id`. For a job, it writes it to the
/// stdin of the process. For the stdio channel |channel-stdio|,
/// it writes to Nvim's stdout. For an internal terminal instance
-/// (|nvim_open_term()|) it writes directly to terimal output.
+/// (|nvim_open_term()|) it writes directly to terminal output.
/// See |channel-bytes| for more information.
///
/// This function writes raw data, not RPC messages. If the channel
@@ -1538,10 +1563,10 @@ Dictionary nvim_get_mode(void)
/// @param mode Mode short-name ("n", "i", "v", ...)
/// @returns Array of maparg()-like dictionaries describing mappings.
/// The "buffer" key is always zero.
-ArrayOf(Dictionary) nvim_get_keymap(String mode)
+ArrayOf(Dictionary) nvim_get_keymap(uint64_t channel_id, String mode)
FUNC_API_SINCE(3)
{
- return keymap_array(mode, NULL);
+ return keymap_array(mode, NULL, channel_id == LUA_INTERNAL_CALL);
}
/// Sets a global |mapping| for the given mode.
@@ -1561,18 +1586,23 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode)
/// nmap <nowait> <Space><NL> <Nop>
/// </pre>
///
+/// @param channel_id
/// @param mode Mode short-name (map command prefix: "n", "i", "v", "x", …)
/// or "!" for |:map!|, or empty string for |:map|.
/// @param lhs Left-hand-side |{lhs}| of the mapping.
/// @param rhs Right-hand-side |{rhs}| of the mapping.
/// @param opts Optional parameters map. Accepts all |:map-arguments|
-/// as keys excluding |<buffer>| but including |noremap|.
+/// as keys excluding |<buffer>| but including |noremap| and "desc".
+/// "desc" can be used to give a description to keymap.
+/// When called from Lua, also accepts a "callback" key that takes
+/// a Lua function to call when the mapping is executed.
/// Values are Booleans. Unknown key is an error.
/// @param[out] err Error details, if any.
-void nvim_set_keymap(String mode, String lhs, String rhs, Dict(keymap) *opts, Error *err)
+void nvim_set_keymap(uint64_t channel_id, String mode, String lhs, String rhs, Dict(keymap) *opts,
+ Error *err)
FUNC_API_SINCE(6)
{
- modify_keymap(-1, false, mode, lhs, rhs, opts, err);
+ modify_keymap(channel_id, -1, false, mode, lhs, rhs, opts, err);
}
/// Unmaps a global |mapping| for the given mode.
@@ -1580,10 +1610,10 @@ void nvim_set_keymap(String mode, String lhs, String rhs, Dict(keymap) *opts, Er
/// To unmap a buffer-local mapping, use |nvim_buf_del_keymap()|.
///
/// @see |nvim_set_keymap()|
-void nvim_del_keymap(String mode, String lhs, Error *err)
+void nvim_del_keymap(uint64_t channel_id, String mode, String lhs, Error *err)
FUNC_API_SINCE(6)
{
- nvim_buf_del_keymap(-1, mode, lhs, err);
+ nvim_buf_del_keymap(channel_id, -1, mode, lhs, err);
}
/// Gets a map of global (non-buffer-local) Ex commands.
@@ -1741,7 +1771,7 @@ Array nvim_list_chans(void)
/// 1. To perform several requests from an async context atomically, i.e.
/// without interleaving redraws, RPC requests from other clients, or user
/// interactions (however API methods may trigger autocommands or event
-/// processing which have such side-effects, e.g. |:sleep| may wake timers).
+/// processing which have such side effects, e.g. |:sleep| may wake timers).
/// 2. To minimize RPC overhead (roundtrips) of a sequence of many requests.
///
/// @param channel_id
@@ -1927,7 +1957,7 @@ Dictionary nvim__stats(void)
Dictionary rv = ARRAY_DICT_INIT;
PUT(rv, "fsync", INTEGER_OBJ(g_stats.fsync));
PUT(rv, "redraw", INTEGER_OBJ(g_stats.redraw));
- PUT(rv, "lua_refcount", INTEGER_OBJ(nlua_refcount));
+ PUT(rv, "lua_refcount", INTEGER_OBJ(nlua_get_global_ref_count()));
return rv;
}
@@ -2101,7 +2131,7 @@ void nvim__screenshot(String path)
}
-/// Deletes a uppercase/file named mark. See |mark-motions|.
+/// Deletes an uppercase/file named mark. See |mark-motions|.
///
/// @note fails with error if a lowercase or buffer local named mark is used.
/// @param name Mark name
@@ -2231,7 +2261,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
Dictionary result = ARRAY_DICT_INIT;
int maxwidth;
- char fillchar = 0;
+ int fillchar = 0;
Window window = 0;
bool use_tabline = false;
bool highlights = false;
@@ -2246,12 +2276,12 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
}
if (HAS_KEY(opts->fillchar)) {
- if (opts->fillchar.type != kObjectTypeString || opts->fillchar.data.string.size > 1) {
- api_set_error(err, kErrorTypeValidation, "fillchar must be an ASCII character");
+ if (opts->fillchar.type != kObjectTypeString || opts->fillchar.data.string.size == 0
+ || char2cells(fillchar = utf_ptr2char((char_u *)opts->fillchar.data.string.data)) != 1
+ || (size_t)utf_char2len(fillchar) != opts->fillchar.data.string.size) {
+ api_set_error(err, kErrorTypeValidation, "fillchar must be a single-width character");
return result;
}
-
- fillchar = opts->fillchar.data.string.data[0];
}
if (HAS_KEY(opts->highlights)) {
@@ -2278,11 +2308,16 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
fillchar = ' ';
} else {
wp = find_window_by_handle(window, err);
+
+ if (wp == NULL) {
+ api_set_error(err, kErrorTypeException, "unknown winid %d", window);
+ return result;
+ }
ewp = wp;
if (fillchar == 0) {
int attr;
- fillchar = (char)fillchar_status(&attr, wp);
+ fillchar = fillchar_status(&attr, wp);
}
}
@@ -2310,7 +2345,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
sizeof(buf),
(char_u *)str.data,
false,
- (char_u)fillchar,
+ fillchar,
maxwidth,
hltab_ptr,
NULL);
@@ -2363,3 +2398,55 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
return result;
}
+
+/// Create a new user command |user-commands|
+///
+/// {name} is the name of the new command. The name must begin with an uppercase letter.
+///
+/// {command} is the replacement text or Lua function to execute.
+///
+/// Example:
+/// <pre>
+/// :call nvim_add_user_command('SayHello', 'echo "Hello world!"', {})
+/// :SayHello
+/// Hello world!
+/// </pre>
+///
+/// @param name Name of the new user command. Must begin with an uppercase letter.
+/// @param command Replacement command to execute when this user command is executed. When called
+/// from Lua, the command can also be a Lua function. The function is called with a
+/// single table argument that contains the following keys:
+/// - args: (string) The args passed to the command, if any |<args>|
+/// - fargs: (table) The args split by unescaped whitespace (when more than one
+/// argument is allowed), if any |<f-args>|
+/// - bang: (boolean) "true" if the command was executed with a ! modifier |<bang>|
+/// - line1: (number) The starting line of the command range |<line1>|
+/// - line2: (number) The final line of the command range |<line2>|
+/// - range: (number) The number of items in the command range: 0, 1, or 2 |<range>|
+/// - count: (number) Any count supplied |<count>|
+/// - reg: (string) The optional register, if specified |<reg>|
+/// - mods: (string) Command modifiers, if any |<mods>|
+/// @param opts Optional command attributes. See |command-attributes| for more details. To use
+/// boolean attributes (such as |:command-bang| or |:command-bar|) set the value to
+/// "true". In addition to the string options listed in |:command-complete|, the
+/// "complete" key also accepts a Lua function which works like the "customlist"
+/// completion mode |:command-completion-customlist|. Additional parameters:
+/// - desc: (string) Used for listing the command when a Lua function is used for
+/// {command}.
+/// - force: (boolean, default true) Override any previous definition.
+/// @param[out] err Error details, if any.
+void nvim_add_user_command(String name, Object command, Dict(user_command) *opts, Error *err)
+ FUNC_API_SINCE(9)
+{
+ add_user_command(name, command, opts, 0, err);
+}
+
+/// Delete a user-defined command.
+///
+/// @param name Name of the command to delete.
+/// @param[out] err Error details, if any.
+void nvim_del_user_command(String name, Error *err)
+ FUNC_API_SINCE(9)
+{
+ nvim_buf_del_user_command(-1, name, err);
+}