aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/api')
-rw-r--r--src/nvim/api/buffer.c116
-rw-r--r--src/nvim/api/private/defs.h11
-rw-r--r--src/nvim/api/private/helpers.c226
-rw-r--r--src/nvim/api/private/helpers.h1
-rw-r--r--src/nvim/api/ui.c79
-rw-r--r--src/nvim/api/ui_events.in.h6
-rw-r--r--src/nvim/api/vim.c358
-rw-r--r--src/nvim/api/window.c71
8 files changed, 658 insertions, 210 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 3613a8f8bc..9a5ffecad4 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -15,6 +15,7 @@
#include "nvim/buffer.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
+#include "nvim/getchar.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/misc1.h"
@@ -49,7 +50,7 @@
/// Gets the buffer line count
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param[out] err Error details, if any
/// @return Line count, or 0 for unloaded buffer. |api-buffer|
Integer nvim_buf_line_count(Buffer buffer, Error *err)
@@ -97,15 +98,16 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err)
return rv;
}
-/// Activate updates from this buffer to the current channel.
+/// Activates buffer-update events on the channel.
///
-/// @param buffer The buffer handle
+/// @param channel_id
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param send_buffer Set to true if the initial notification should contain
/// the whole buffer. If so, the first notification will be a
/// `nvim_buf_lines_event`. Otherwise, the first notification will be
/// a `nvim_buf_changedtick_event`
/// @param opts Optional parameters. Reserved for future use.
-/// @param[out] err Details of an error that may have occurred
+/// @param[out] err Error details, if any
/// @return False when updates couldn't be enabled because the buffer isn't
/// loaded or `opts` contained an invalid key; otherwise True.
Boolean nvim_buf_attach(uint64_t channel_id,
@@ -128,11 +130,12 @@ Boolean nvim_buf_attach(uint64_t channel_id,
return buf_updates_register(buf, channel_id, send_buffer);
}
-//
-/// Deactivate updates from this buffer to the current channel.
+
+/// Deactivates buffer-update events on the channel.
///
-/// @param buffer The buffer handle
-/// @param[out] err Details of an error that may have occurred
+/// @param channel_id
+/// @param buffer Buffer handle, or 0 for current buffer
+/// @param[out] err Error details, if any
/// @return False when updates couldn't be disabled because the buffer
/// isn't loaded; otherwise True.
Boolean nvim_buf_detach(uint64_t channel_id,
@@ -221,7 +224,8 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
/// Out-of-bounds indices are clamped to the nearest valid value, unless
/// `strict_indexing` is set.
///
-/// @param buffer Buffer handle
+/// @param channel_id
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param start First line index
/// @param end Last line index (exclusive)
/// @param strict_indexing Whether out-of-bounds should be an error.
@@ -290,7 +294,7 @@ end:
/// newend = end + int(include_end) + int(end < 0)
/// int(bool) = 1 if bool is true else 0
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param start First line index
/// @param end Last line index
/// @param include_start True if the slice includes the `start` parameter
@@ -324,7 +328,8 @@ void buffer_set_line_slice(Buffer buffer,
/// Out-of-bounds indices are clamped to the nearest valid value, unless
/// `strict_indexing` is set.
///
-/// @param buffer Buffer handle
+/// @param channel_id
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param start First line index
/// @param end Last line index (exclusive)
/// @param strict_indexing Whether out-of-bounds should be an error.
@@ -470,6 +475,7 @@ void nvim_buf_set_lines(uint64_t channel_id,
false);
changed_lines((linenr_T)start, 0, (linenr_T)end, (long)extra, true);
+ fix_cursor((linenr_T)start, (linenr_T)end, (linenr_T)extra);
end:
for (size_t i = 0; i < new_len; i++) {
@@ -491,7 +497,7 @@ end:
/// Unlike |line2byte()|, throws error for out-of-bounds indexing.
/// Returns -1 for unloaded buffer.
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param index Line index
/// @param[out] err Error details, if any
/// @return Integer byte offset, or -1 for unloaded buffer.
@@ -518,7 +524,7 @@ Integer nvim_buf_get_offset(Buffer buffer, Integer index, Error *err)
/// Gets a buffer-scoped (b:) variable.
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param name Variable name
/// @param[out] err Error details, if any
/// @return Variable value
@@ -536,7 +542,7 @@ Object nvim_buf_get_var(Buffer buffer, String name, Error *err)
/// Gets a changed tick of a buffer
///
-/// @param[in] buffer Buffer handle.
+/// @param[in] buffer Buffer handle, or 0 for current buffer
/// @param[out] err Error details, if any
///
/// @return `b:changedtick` value.
@@ -555,7 +561,7 @@ Integer nvim_buf_get_changedtick(Buffer buffer, Error *err)
/// Gets a list of buffer-local |mapping| definitions.
///
/// @param mode Mode short-name ("n", "i", "v", ...)
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param[out] err Error details, if any
/// @returns Array of maparg()-like dictionaries describing mappings.
/// The "buffer" key holds the associated buffer handle.
@@ -571,9 +577,34 @@ ArrayOf(Dictionary) nvim_buf_get_keymap(Buffer buffer, String mode, Error *err)
return keymap_array(mode, buf);
}
+/// Sets a buffer-local |mapping| for the given mode.
+///
+/// @see |nvim_set_keymap()|
+///
+/// @param buffer Buffer handle, or 0 for current buffer
+void nvim_buf_set_keymap(Buffer buffer, String mode, String lhs, String rhs,
+ Dictionary opts, Error *err)
+ FUNC_API_SINCE(6)
+{
+ modify_keymap(buffer, false, mode, lhs, rhs, opts, err);
+}
+
+/// Unmaps a buffer-local |mapping| for the given mode.
+///
+/// @see |nvim_del_keymap()|
+///
+/// @param buffer Buffer handle, or 0 for current buffer
+void nvim_buf_del_keymap(Buffer buffer, String mode, String lhs, Error *err)
+ FUNC_API_SINCE(6)
+{
+ String rhs = { .data = "", .size = 0 };
+ Dictionary opts = ARRAY_DICT_INIT;
+ modify_keymap(buffer, true, mode, lhs, rhs, opts, err);
+}
+
/// Gets a map of buffer-local |user-commands|.
///
-/// @param buffer Buffer handle.
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param opts Optional parameters. Currently not used.
/// @param[out] err Error details, if any.
///
@@ -613,7 +644,7 @@ Dictionary nvim_buf_get_commands(Buffer buffer, Dictionary opts, Error *err)
/// Sets a buffer-scoped (b:) variable
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param name Variable name
/// @param value Variable value
/// @param[out] err Error details, if any
@@ -631,7 +662,7 @@ void nvim_buf_set_var(Buffer buffer, String name, Object value, Error *err)
/// Removes a buffer-scoped (b:) variable
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param name Variable name
/// @param[out] err Error details, if any
void nvim_buf_del_var(Buffer buffer, String name, Error *err)
@@ -650,7 +681,7 @@ void nvim_buf_del_var(Buffer buffer, String name, Error *err)
///
/// @deprecated
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param name Variable name
/// @param value Variable value
/// @param[out] err Error details, if any
@@ -673,7 +704,7 @@ Object buffer_set_var(Buffer buffer, String name, Object value, Error *err)
///
/// @deprecated
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param name Variable name
/// @param[out] err Error details, if any
/// @return Old value
@@ -691,7 +722,7 @@ Object buffer_del_var(Buffer buffer, String name, Error *err)
/// Gets a buffer option value
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param name Option name
/// @param[out] err Error details, if any
/// @return Option value
@@ -710,7 +741,8 @@ Object nvim_buf_get_option(Buffer buffer, String name, Error *err)
/// Sets a buffer option value. Passing 'nil' as value deletes the option (only
/// works if there's a global fallback)
///
-/// @param buffer Buffer handle
+/// @param channel_id
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param name Option name
/// @param value Option value
/// @param[out] err Error details, if any
@@ -732,7 +764,7 @@ void nvim_buf_set_option(uint64_t channel_id, Buffer buffer,
/// @deprecated The buffer number now is equal to the object id,
/// so there is no need to use this function.
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param[out] err Error details, if any
/// @return Buffer number
Integer nvim_buf_get_number(Buffer buffer, Error *err)
@@ -751,7 +783,7 @@ Integer nvim_buf_get_number(Buffer buffer, Error *err)
/// Gets the full file name for the buffer
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param[out] err Error details, if any
/// @return Buffer name
String nvim_buf_get_name(Buffer buffer, Error *err)
@@ -769,7 +801,7 @@ String nvim_buf_get_name(Buffer buffer, Error *err)
/// Sets the full file name for a buffer
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param name Buffer name
/// @param[out] err Error details, if any
void nvim_buf_set_name(Buffer buffer, String name, Error *err)
@@ -801,7 +833,7 @@ void nvim_buf_set_name(Buffer buffer, String name, Error *err)
/// Checks if a buffer is valid and loaded. See |api-buffer| for more info
/// about unloaded buffers.
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @return true if the buffer is valid and loaded, false otherwise.
Boolean nvim_buf_is_loaded(Buffer buffer)
FUNC_API_SINCE(5)
@@ -817,7 +849,7 @@ Boolean nvim_buf_is_loaded(Buffer buffer)
/// @note Even if a buffer is valid it may have been unloaded. See |api-buffer|
/// for more info about unloaded buffers.
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @return true if the buffer is valid, false otherwise.
Boolean nvim_buf_is_valid(Buffer buffer)
FUNC_API_SINCE(1)
@@ -849,7 +881,7 @@ void buffer_insert(Buffer buffer,
/// Return a tuple (row,col) representing the position of the named mark
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param name Mark name
/// @param[out] err Error details, if any
/// @return (row, col) tuple
@@ -914,7 +946,7 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err)
/// supported for backwards compatibility, new code should use
/// |nvim_create_namespace| to create a new empty namespace.
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param ns_id namespace to use or -1 for ungrouped highlight
/// @param hl_group Name of the highlight group to use
/// @param line Line to highlight (zero-indexed)
@@ -964,7 +996,7 @@ Integer nvim_buf_add_highlight(Buffer buffer,
/// To clear the namespace in the entire buffer, pass in 0 and -1 to
/// line_start and line_end respectively.
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param ns_id Namespace to clear, or -1 to clear all namespaces.
/// @param line_start Start of range of lines to clear
/// @param line_end End of range of lines to clear (exclusive) or -1 to clear
@@ -997,7 +1029,7 @@ void nvim_buf_clear_namespace(Buffer buffer,
///
/// @deprecated use |nvim_buf_clear_namespace|.
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param ns_id Namespace to clear, or -1 to clear all.
/// @param line_start Start of range of lines to clear
/// @param line_end End of range of lines to clear (exclusive) or -1 to clear
@@ -1031,7 +1063,7 @@ void nvim_buf_clear_highlight(Buffer buffer,
/// As a shorthand, `ns_id = 0` can be used to create a new namespace for the
/// virtual text, the allocated id is then returned.
///
-/// @param buffer Buffer handle
+/// @param buffer Buffer handle, or 0 for current buffer
/// @param ns_id Namespace to use or 0 to create a namespace,
/// or -1 for a ungrouped annotation
/// @param line Line to annotate with virtual text (zero-indexed)
@@ -1101,6 +1133,26 @@ free_exit:
return 0;
}
+// Check if deleting lines made the cursor position invalid.
+// Changed lines from `lo` to `hi`; added `extra` lines (negative if deleted).
+static void fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
+{
+ if (curwin->w_cursor.lnum >= lo) {
+ // Adjust cursor position if it's in/after the changed lines.
+ if (curwin->w_cursor.lnum >= hi) {
+ curwin->w_cursor.lnum += extra;
+ check_cursor_col();
+ } else if (extra < 0) {
+ curwin->w_cursor.lnum = lo;
+ check_cursor();
+ } else {
+ check_cursor_col();
+ }
+ changed_cline_bef_curs();
+ }
+ invalidate_botline();
+}
+
// Normalizes 0-based indexes to buffer line numbers
static int64_t normalize_index(buf_T *buf, int64_t index, bool *oob)
{
diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h
index feca140547..978c55691b 100644
--- a/src/nvim/api/private/defs.h
+++ b/src/nvim/api/private/defs.h
@@ -29,14 +29,13 @@ typedef enum {
} ErrorType;
typedef enum {
- kMessageTypeRequest,
- kMessageTypeResponse,
- kMessageTypeNotification
+ kMessageTypeUnknown = -1,
+ // Per msgpack-rpc spec.
+ kMessageTypeRequest = 0,
+ kMessageTypeResponse = 1,
+ kMessageTypeNotification = 2,
} MessageType;
-/// Used as the message ID of notifications.
-#define NO_RESPONSE UINT64_MAX
-
/// Mask for all internal calls
#define INTERNAL_CALL_MASK (((uint64_t)1) << (sizeof(uint64_t) * 8 - 1))
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index c2b382804d..521ec11906 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -744,6 +744,232 @@ String ga_take_string(garray_T *ga)
return str;
}
+/// Set, tweak, or remove a mapping in a mode. Acts as the implementation for
+/// functions like @ref nvim_buf_set_keymap.
+///
+/// Arguments are handled like @ref nvim_set_keymap unless noted.
+/// @param buffer Buffer handle for a specific buffer, or 0 for the current
+/// buffer, or -1 to signify global behavior ("all buffers")
+/// @param is_unmap When true, removes the mapping that matches {lhs}.
+void modify_keymap(Buffer buffer, bool is_unmap, String mode, String lhs,
+ String rhs, Dictionary opts, Error *err)
+{
+ char *err_msg = NULL; // the error message to report, if any
+ char *err_arg = NULL; // argument for the error message format string
+ ErrorType err_type = kErrorTypeNone;
+
+ char_u *lhs_buf = NULL;
+ char_u *rhs_buf = NULL;
+
+ bool global = (buffer == -1);
+ if (global) {
+ buffer = 0;
+ }
+ buf_T *target_buf = find_buffer_by_handle(buffer, err);
+
+ MapArguments parsed_args;
+ memset(&parsed_args, 0, sizeof(parsed_args));
+ if (parse_keymap_opts(opts, &parsed_args, err)) {
+ goto fail_and_free;
+ }
+ parsed_args.buffer = !global;
+
+ set_maparg_lhs_rhs((char_u *)lhs.data, lhs.size,
+ (char_u *)rhs.data, rhs.size,
+ CPO_TO_CPO_FLAGS, &parsed_args);
+
+ if (parsed_args.lhs_len > MAXMAPLEN) {
+ err_msg = "LHS exceeds maximum map length: %s";
+ err_arg = lhs.data;
+ err_type = kErrorTypeValidation;
+ goto fail_with_message;
+ }
+
+ if (mode.size > 1) {
+ err_msg = "Shortname is too long: %s";
+ err_arg = mode.data;
+ err_type = kErrorTypeValidation;
+ goto fail_with_message;
+ }
+ int mode_val; // integer value of the mapping mode, to be passed to do_map()
+ char_u *p = (char_u *)((mode.size) ? mode.data : "m");
+ if (STRNCMP(p, "!", 2) == 0) {
+ mode_val = get_map_mode(&p, true); // mapmode-ic
+ } else {
+ mode_val = get_map_mode(&p, false);
+ if ((mode_val == VISUAL + SELECTMODE + NORMAL + OP_PENDING)
+ && mode.size > 0) {
+ // get_map_mode() treats unrecognized mode shortnames as ":map".
+ // This is an error unless the given shortname was empty string "".
+ err_msg = "Invalid mode shortname: \"%s\"";
+ err_arg = (char *)p;
+ err_type = kErrorTypeValidation;
+ goto fail_with_message;
+ }
+ }
+
+ if (parsed_args.lhs_len == 0) {
+ err_msg = "Invalid (empty) LHS";
+ err_arg = "";
+ err_type = kErrorTypeValidation;
+ goto fail_with_message;
+ }
+
+ bool is_noremap = parsed_args.noremap;
+ assert(!(is_unmap && is_noremap));
+
+ if (!is_unmap && (parsed_args.rhs_len == 0 && !parsed_args.rhs_is_noop)) {
+ if (rhs.size == 0) { // assume that the user wants RHS to be a <Nop>
+ parsed_args.rhs_is_noop = true;
+ } else {
+ // the given RHS was nonempty and not a <Nop>, but was parsed as if it
+ // were empty?
+ assert(false && "Failed to parse nonempty RHS!");
+ err_msg = "Parsing of nonempty RHS failed: %s";
+ err_arg = rhs.data;
+ err_type = kErrorTypeException;
+ goto fail_with_message;
+ }
+ } else if (is_unmap && parsed_args.rhs_len) {
+ err_msg = "Gave nonempty RHS in unmap command: %s";
+ err_arg = (char *)parsed_args.rhs;
+ err_type = kErrorTypeValidation;
+ goto fail_with_message;
+ }
+
+ // buf_do_map() reads noremap/unmap as its own argument.
+ int maptype_val = 0;
+ if (is_unmap) {
+ maptype_val = 1;
+ } else if (is_noremap) {
+ maptype_val = 2;
+ }
+
+ switch (buf_do_map(maptype_val, &parsed_args, mode_val, 0, target_buf)) {
+ case 0:
+ break;
+ case 1:
+ api_set_error(err, kErrorTypeException, (char *)e_invarg, 0);
+ goto fail_and_free;
+ case 2:
+ api_set_error(err, kErrorTypeException, (char *)e_nomap, 0);
+ goto fail_and_free;
+ case 5:
+ api_set_error(err, kErrorTypeException,
+ "E227: mapping already exists for %s", parsed_args.lhs);
+ goto fail_and_free;
+ default:
+ assert(false && "Unrecognized return code!");
+ goto fail_and_free;
+ } // switch
+
+ xfree(lhs_buf);
+ xfree(rhs_buf);
+ xfree(parsed_args.rhs);
+ xfree(parsed_args.orig_rhs);
+
+ return;
+
+fail_with_message:
+ api_set_error(err, err_type, err_msg, err_arg);
+
+fail_and_free:
+ xfree(lhs_buf);
+ xfree(rhs_buf);
+ xfree(parsed_args.rhs);
+ xfree(parsed_args.orig_rhs);
+ return;
+}
+
+/// Read in the given opts, setting corresponding flags in `out`.
+///
+/// @param opts A dictionary passed to @ref nvim_set_keymap or
+/// @ref nvim_buf_set_keymap.
+/// @param[out] out MapArguments object in which to set parsed
+/// |:map-arguments| flags.
+/// @param[out] err Error details, if any.
+///
+/// @returns Zero on success, nonzero on failure.
+Integer parse_keymap_opts(Dictionary opts, MapArguments *out, Error *err)
+{
+ char *err_msg = NULL; // the error message to report, if any
+ char *err_arg = NULL; // argument for the error message format string
+ ErrorType err_type = kErrorTypeNone;
+
+ out->buffer = false;
+ out->nowait = false;
+ out->silent = false;
+ out->script = false;
+ out->expr = false;
+ out->unique = false;
+
+ for (size_t i = 0; i < opts.size; i++) {
+ KeyValuePair *key_and_val = &opts.items[i];
+ char *optname = key_and_val->key.data;
+
+ if (key_and_val->value.type != kObjectTypeBoolean) {
+ err_msg = "Gave non-boolean value for an opt: %s";
+ err_arg = optname;
+ err_type = kErrorTypeValidation;
+ goto fail_with_message;
+ }
+
+ bool was_valid_opt = false;
+ switch (optname[0]) {
+ // note: strncmp up to and including the null terminator, so that
+ // "nowaitFoobar" won't match against "nowait"
+
+ // don't recognize 'buffer' as a key; user shouldn't provide <buffer>
+ // when calling nvim_set_keymap or nvim_buf_set_keymap, since it can be
+ // inferred from which function they called
+ case 'n':
+ if (STRNCMP(optname, "noremap", 8) == 0) {
+ was_valid_opt = true;
+ out->noremap = key_and_val->value.data.boolean;
+ } else if (STRNCMP(optname, "nowait", 7) == 0) {
+ was_valid_opt = true;
+ out->nowait = key_and_val->value.data.boolean;
+ }
+ break;
+ case 's':
+ if (STRNCMP(optname, "silent", 7) == 0) {
+ was_valid_opt = true;
+ out->silent = key_and_val->value.data.boolean;
+ } else if (STRNCMP(optname, "script", 7) == 0) {
+ was_valid_opt = true;
+ out->script = key_and_val->value.data.boolean;
+ }
+ break;
+ case 'e':
+ if (STRNCMP(optname, "expr", 5) == 0) {
+ was_valid_opt = true;
+ out->expr = key_and_val->value.data.boolean;
+ }
+ break;
+ case 'u':
+ if (STRNCMP(optname, "unique", 7) == 0) {
+ was_valid_opt = true;
+ out->unique = key_and_val->value.data.boolean;
+ }
+ break;
+ default:
+ break;
+ } // switch
+ if (!was_valid_opt) {
+ err_msg = "Invalid key: %s";
+ err_arg = optname;
+ err_type = kErrorTypeValidation;
+ goto fail_with_message;
+ }
+ } // for
+
+ return 0;
+
+fail_with_message:
+ api_set_error(err, err_type, err_msg, err_arg);
+ return 1;
+}
+
/// Collects `n` buffer lines into array `l`, optionally replacing newlines
/// with NUL.
///
diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h
index 0634764f13..cc74824402 100644
--- a/src/nvim/api/private/helpers.h
+++ b/src/nvim/api/private/helpers.h
@@ -5,6 +5,7 @@
#include "nvim/api/private/defs.h"
#include "nvim/vim.h"
+#include "nvim/getchar.h"
#include "nvim/memory.h"
#include "nvim/ex_eval.h"
#include "nvim/lib/kvec.h"
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index d3cbb46dad..4f28ea5af3 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -29,11 +29,12 @@ typedef struct {
uint64_t channel_id;
Array buffer;
- int hl_id; // current higlight for legacy put event
- Integer cursor_row, cursor_col; // Intended visibule cursor position
+ int hl_id; // Current highlight for legacy put event.
+ Integer cursor_row, cursor_col; // Intended visible cursor position.
// Position of legacy cursor, used both for drawing and visible user cursor.
Integer client_row, client_col;
+ bool wildmenu_active;
} UIData;
static PMap(uint64_t) *connected_uis = NULL;
@@ -75,6 +76,21 @@ void remote_ui_wait_for_attach(void)
pmap_has(uint64_t)(connected_uis, CHAN_STDIO));
}
+/// Activates UI events on the channel.
+///
+/// Entry point of all UI clients. Allows |\-\-embed| to continue startup.
+/// Implies that the client is ready to show the UI. Adds the client to the
+/// list of UIs. |nvim_list_uis()|
+///
+/// @note If multiple UI clients are attached, the global screen dimensions
+/// degrade to the smallest client. E.g. if client A requests 80x40 but
+/// client B requests 200x100, the global screen has size 80x40.
+///
+/// @param channel_id
+/// @param width Requested screen columns
+/// @param height Requested screen rows
+/// @param options |ui-option| map
+/// @param[out] err Error details, if any
void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
Dictionary options, Error *err)
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
@@ -94,6 +110,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
ui->width = (int)width;
ui->height = (int)height;
ui->rgb = true;
+ ui->override = false;
ui->grid_resize = remote_ui_grid_resize;
ui->grid_clear = remote_ui_grid_clear;
ui->grid_cursor_goto = remote_ui_grid_cursor_goto;
@@ -146,6 +163,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
data->buffer = (Array)ARRAY_DICT_INIT;
data->hl_id = 0;
data->client_col = -1;
+ data->wildmenu_active = false;
ui->data = data;
pmap_put(uint64_t)(connected_uis, channel_id, ui);
@@ -162,6 +180,12 @@ void ui_attach(uint64_t channel_id, Integer width, Integer height,
api_free_dictionary(opts);
}
+/// Deactivates UI events on the channel.
+///
+/// Removes the client from the list of UIs. |nvim_list_uis()|
+///
+/// @param channel_id
+/// @param[out] err Error details, if any
void nvim_ui_detach(uint64_t channel_id, Error *err)
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
{
@@ -213,6 +237,15 @@ void nvim_ui_set_option(uint64_t channel_id, String name,
static void ui_set_option(UI *ui, bool init, String name, Object value,
Error *error)
{
+ if (strequal(name.data, "override")) {
+ if (value.type != kObjectTypeBoolean) {
+ api_set_error(error, kErrorTypeValidation, "override must be a Boolean");
+ return;
+ }
+ ui->override = value.data.boolean;
+ return;
+ }
+
if (strequal(name.data, "rgb")) {
if (value.type != kObjectTypeBoolean) {
api_set_error(error, kErrorTypeValidation, "rgb must be a Boolean");
@@ -262,20 +295,22 @@ static void ui_set_option(UI *ui, bool init, String name, Object value,
///
/// On invalid grid handle, fails with error.
///
+/// @param channel_id
/// @param grid The handle of the grid to be changed.
/// @param width The new requested width.
/// @param height The new requested height.
+/// @param[out] err Error details, if any
void nvim_ui_try_resize_grid(uint64_t channel_id, Integer grid, Integer width,
- Integer height, Error *error)
+ Integer height, Error *err)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY
{
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
- api_set_error(error, kErrorTypeException,
+ api_set_error(err, kErrorTypeException,
"UI not attached to channel: %" PRId64, channel_id);
return;
}
- ui_grid_resize((handle_T)grid, (int)width, (int)height, error);
+ ui_grid_resize((handle_T)grid, (int)width, (int)height, err);
}
/// Pushes data into UI.UIData, to be consumed later by remote_ui_flush().
@@ -586,6 +621,7 @@ static Array translate_firstarg(UI *ui, Array args)
static void remote_ui_event(UI *ui, char *name, Array args, bool *args_consumed)
{
+ UIData *data = ui->data;
if (!ui->ui_ext[kUILinegrid]) {
// the representation of highlights in cmdline changed, translate back
// never consumes args
@@ -611,6 +647,39 @@ static void remote_ui_event(UI *ui, char *name, Array args, bool *args_consumed)
}
}
+ // Back-compat: translate popupmenu_xx to legacy wildmenu_xx.
+ if (ui->ui_ext[kUIWildmenu]) {
+ if (strequal(name, "popupmenu_show")) {
+ data->wildmenu_active = (args.items[4].data.integer == -1)
+ || !ui->ui_ext[kUIPopupmenu];
+ if (data->wildmenu_active) {
+ Array new_args = ARRAY_DICT_INIT;
+ Array items = args.items[0].data.array;
+ Array new_items = ARRAY_DICT_INIT;
+ for (size_t i = 0; i < items.size; i++) {
+ ADD(new_items, copy_object(items.items[i].data.array.items[0]));
+ }
+ ADD(new_args, ARRAY_OBJ(new_items));
+ push_call(ui, "wildmenu_show", new_args);
+ if (args.items[1].data.integer != -1) {
+ Array new_args2 = ARRAY_DICT_INIT;
+ ADD(new_args2, args.items[1]);
+ push_call(ui, "wildmenu_select", new_args);
+ }
+ return;
+ }
+ } else if (strequal(name, "popupmenu_select")) {
+ if (data->wildmenu_active) {
+ name = "wildmenu_select";
+ }
+ } else if (strequal(name, "popupmenu_hide")) {
+ if (data->wildmenu_active) {
+ name = "wildmenu_hide";
+ }
+ }
+ }
+
+
Array my_args = ARRAY_DICT_INIT;
// Objects are currently single-reference
// make a copy, but only if necessary
diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h
index b89c5b6014..a1d25766fe 100644
--- a/src/nvim/api/ui_events.in.h
+++ b/src/nvim/api/ui_events.in.h
@@ -143,11 +143,11 @@ void cmdline_block_hide(void)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void wildmenu_show(Array items)
- FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
+ FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL FUNC_API_BRIDGE_IMPL;
void wildmenu_select(Integer selected)
- FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
+ FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL FUNC_API_BRIDGE_IMPL;
void wildmenu_hide(void)
- FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
+ FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL FUNC_API_BRIDGE_IMPL;
void msg_show(String kind, Array content, Boolean replace_last)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index cb5ed5ecda..b8c863704a 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -15,6 +15,7 @@
#include "nvim/api/private/defs.h"
#include "nvim/api/private/dispatch.h"
#include "nvim/api/buffer.h"
+#include "nvim/api/window.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/lua/executor.h"
@@ -213,8 +214,8 @@ Integer nvim_input(String keys)
/// Send mouse event from GUI.
///
-/// The call is non-blocking. It doesn't wait on any resulting action, but
-/// queues the event to be processed soon by the event loop.
+/// Non-blocking: does not wait on any result, but queues the event to be
+/// processed soon by the event loop.
///
/// @note Currently this doesn't support "scripting" multiple mouse events
/// by calling it multiple times in a loop: the intermediate mouse
@@ -232,6 +233,7 @@ Integer nvim_input(String keys)
/// @param grid Grid number if the client uses |ui-multigrid|, else 0.
/// @param row Mouse row-position (zero-based, like redraw events)
/// @param col Mouse column-position (zero-based, like redraw events)
+/// @param[out] err Error details, if any
void nvim_input_mouse(String button, String action, String modifier,
Integer grid, Integer row, Integer col, Error *err)
FUNC_API_SINCE(6) FUNC_API_ASYNC
@@ -681,14 +683,14 @@ void nvim_set_current_dir(String dir, Error *err)
try_start();
- if (vim_chdir((char_u *)string, kCdScopeGlobal)) {
+ if (vim_chdir((char_u *)string)) {
if (!try_end(err)) {
api_set_error(err, kErrorTypeException, "Failed to change directory");
}
return;
}
- post_chdir(kCdScopeGlobal);
+ post_chdir(kCdScopeGlobal, true);
try_end(err);
}
@@ -755,9 +757,9 @@ void nvim_del_var(String name, Error *err)
/// @deprecated
/// @see nvim_set_var
-/// @return Old value or nil if there was no previous value.
/// @warning May return nil if there was no previous value
/// OR if previous value was `v:null`.
+/// @return Old value or nil if there was no previous value.
Object vim_set_var(String name, Object value, Error *err)
{
return dict_set_var(&globvardict, name, value, false, true, err);
@@ -805,6 +807,7 @@ Object nvim_get_option(String name, Error *err)
/// Sets an option value.
///
+/// @param channel_id
/// @param name Option name
/// @param value New option value
/// @param[out] err Error details, if any
@@ -937,6 +940,7 @@ Window nvim_get_current_win(void)
/// Sets the current window.
///
/// @param window Window handle
+/// @param[out] err Error details, if any
void nvim_set_current_win(Window window, Error *err)
FUNC_API_SINCE(1)
{
@@ -958,7 +962,7 @@ void nvim_set_current_win(Window window, Error *err)
/// Creates a new, empty, unnamed buffer.
///
-/// @param listed Controls 'buflisted'
+/// @param listed Sets 'buflisted'
/// @param scratch Creates a "throwaway" |scratch-buffer| for temporary work
/// (always 'nomodified')
/// @param[out] err Error details, if any
@@ -997,38 +1001,10 @@ Buffer nvim_create_buf(Boolean listed, Boolean scratch, Error *err)
/// GUI with the |ui-multigrid| extension. External windows are only supported
/// with multigrid GUIs, and are displayed as separate top-level windows.
///
-/// Exactly one of `external` and `relative` must be specified.
+/// For a general overview of floats, see |api-floatwin|.
///
-/// @param buffer handle of buffer to be displayed in the window
-/// @param enter whether the window should be entered (made the current window)
-/// @param width width of window (in character cells)
-/// @param height height of window (in character cells)
-/// @param options dict of options for configuring window positioning
-/// accepts the following keys:
-/// `relative`: If set, the window becomes a floating window. The window
-/// will be placed with row,col coordinates relative one of the
-/// following:
-/// "editor" the global editor grid
-/// "win" a window. Use 'win' option below to specify window id,
-/// or current window will be used by default.
-/// "cursor" the cursor position in current window.
-/// `anchor`: the corner of the float that the row,col position defines
-/// "NW" north-west (default)
-/// "NE" north-east
-/// "SW" south-west
-/// "SE" south-east
-/// `focusable`: Whether window can be focused by wincmds and
-/// mouse events. Defaults to true. Even if set to false, the window
-/// can still be entered using |nvim_set_current_win()| API call.
-/// `row`: row position. Screen cell height are used as unit. Can be
-/// floating point.
-/// `col`: column position. Screen cell width is used as unit. Can be
-/// floating point.
-/// `win`: when using relative='win', window id of the window where the
-/// position is defined.
-/// `external` GUI should display the window as an external
-/// top-level window. Currently accepts no other positioning options
-/// together with this.
+/// Exactly one of `external` and `relative` must be specified. The `width` and
+/// `height` of the new window must be specified.
///
/// With editor positioning row=0, col=0 refers to the top-left corner of the
/// screen-grid and row=Lines-1, Columns-1 refers to the bottom-right corner.
@@ -1042,27 +1018,55 @@ Buffer nvim_create_buf(Boolean listed, Boolean scratch, Error *err)
/// could let floats hover outside of the main window like a tooltip, but
/// this should not be used to specify arbitrary WM screen positions.
///
+/// @param buffer handle of buffer to be displayed in the window
+/// @param enter whether the window should be entered (made the current window)
+/// @param config Dictionary for the window configuration accepts these keys:
+/// - `relative`: If set, the window becomes a floating window. The window
+/// will be placed with row,col coordinates relative to one of the
+/// following:
+/// - "editor" the global editor grid
+/// - "win" a window. Use `win` to specify a window id,
+/// or the current window will be used by default.
+/// "cursor" the cursor position in current window.
+/// - `win`: When using relative='win', window id of the window where the
+/// position is defined.
+/// - `anchor`: The corner of the float that the row,col position defines:
+/// - "NW" north-west (default)
+/// - "NE" north-east
+/// - "SW" south-west
+/// - "SE" south-east
+/// - `height`: window height (in character cells). Minimum of 1.
+/// - `width`: window width (in character cells). Minimum of 1.
+/// - `row`: row position. Screen cell height are used as unit. Can be
+/// floating point.
+/// - `col`: column position. Screen cell width is used as unit. Can be
+/// floating point.
+/// - `focusable`: Whether window can be focused by wincmds and
+/// mouse events. Defaults to true. Even if set to false, the window
+/// can still be entered using |nvim_set_current_win()| API call.
+/// - `external`: GUI should display the window as an external
+/// top-level window. Currently accepts no other positioning
+/// configuration together with this.
/// @param[out] err Error details, if any
-/// @return the window handle or 0 when error
-Window nvim_open_win(Buffer buffer, Boolean enter,
- Integer width, Integer height,
- Dictionary options, Error *err)
+///
+/// @return Window handle, or 0 on error
+Window nvim_open_win(Buffer buffer, Boolean enter, Dictionary config,
+ Error *err)
FUNC_API_SINCE(6)
{
- win_T *old = curwin;
- FloatConfig config = FLOAT_CONFIG_INIT;
- if (!parse_float_config(options, &config, false, err)) {
+ FloatConfig fconfig = FLOAT_CONFIG_INIT;
+ if (!parse_float_config(config, &fconfig, false, err)) {
return 0;
}
- win_T *wp = win_new_float(NULL, (int)width, (int)height, config, err);
+ win_T *wp = win_new_float(NULL, fconfig, err);
if (!wp) {
return 0;
}
- if (buffer > 0) {
- nvim_set_current_buf(buffer, err);
+ if (enter) {
+ win_enter(wp, false);
}
- if (!enter) {
- win_enter(old, false);
+ if (buffer > 0) {
+ nvim_win_set_buf(wp->handle, buffer, err);
}
return wp->handle;
}
@@ -1194,12 +1198,29 @@ void nvim_unsubscribe(uint64_t channel_id, String event)
rpc_unsubscribe(channel_id, e);
}
+/// Returns the 24-bit RGB value of a |nvim_get_color_map()| color name or
+/// "#rrggbb" hexadecimal string.
+///
+/// Example:
+/// <pre>
+/// :echo nvim_get_color_by_name("Pink")
+/// :echo nvim_get_color_by_name("#cbcbcb")
+/// </pre>
+///
+/// @param name Color name or "#rrggbb" string
+/// @return 24-bit RGB value, or -1 for invalid argument.
Integer nvim_get_color_by_name(String name)
FUNC_API_SINCE(1)
{
return name_to_color((char_u *)name.data);
}
+/// Returns a map of color names and RGB values.
+///
+/// Keys are color names (e.g. "Aqua") and values are 24-bit RGB color values
+/// (e.g. 65535).
+///
+/// @return Map of color names and RGB values.
Dictionary nvim_get_color_map(void)
FUNC_API_SINCE(1)
{
@@ -1241,6 +1262,49 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode)
return keymap_array(mode, NULL);
}
+/// Sets a global |mapping| for the given mode.
+///
+/// To set a buffer-local mapping, use |nvim_buf_set_keymap()|.
+///
+/// Unlike |:map|, leading/trailing whitespace is accepted as part of the {lhs}
+/// or {rhs}. Empty {rhs} is |<Nop>|. |keycodes| are replaced as usual.
+///
+/// Example:
+/// <pre>
+/// call nvim_set_keymap('n', ' <NL>', '', {'nowait': v:true})
+/// </pre>
+///
+/// is equivalent to:
+/// <pre>
+/// nmap <nowait> <Space><NL> <Nop>
+/// </pre>
+///
+/// @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|.
+/// 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,
+ Dictionary opts, Error *err)
+ FUNC_API_SINCE(6)
+{
+ modify_keymap(-1, false, mode, lhs, rhs, opts, err);
+}
+
+/// Unmaps a global |mapping| for the given mode.
+///
+/// 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)
+ FUNC_API_SINCE(6)
+{
+ nvim_buf_del_keymap(-1, mode, lhs, err);
+}
+
/// Gets a map of global (non-buffer-local) Ex commands.
///
/// Currently only |user-commands| are supported, not builtin Ex commands.
@@ -1272,47 +1336,48 @@ Array nvim_get_api_info(uint64_t channel_id)
return rv;
}
-/// Identify the client for nvim. Can be called more than once, but subsequent
-/// calls will remove earlier info, which should be resent if it is still
-/// valid. (This could happen if a library first identifies the channel, and a
+/// Identifies the client. Can be called more than once; subsequent calls
+/// remove earlier info, which should be included by the caller if it is
+/// still valid. (E.g. if a library first identifies the channel, then a
/// plugin using that library later overrides that info)
///
-/// @param name short name for the connected client
-/// @param version Dictionary describing the version, with the following
-/// possible keys (all optional)
+/// @param channel_id
+/// @param name Short name for the connected client
+/// @param version Dictionary describing the version, with these
+/// (optional) keys:
/// - "major" major version (defaults to 0 if not set, for no release yet)
/// - "minor" minor version
/// - "patch" patch number
/// - "prerelease" string describing a prerelease, like "dev" or "beta1"
/// - "commit" hash or similar identifier of commit
-/// @param type Must be one of the following values. A client library should
-/// use "remote" if the library user hasn't specified other value.
-/// - "remote" remote client that connected to nvim.
+/// @param type Must be one of the following values. Client libraries should
+/// default to "remote" unless overridden by the user.
+/// - "remote" remote client connected to Nvim.
/// - "ui" gui frontend
-/// - "embedder" application using nvim as a component, for instance
-/// IDE/editor implementing a vim mode.
+/// - "embedder" application using Nvim as a component (for example,
+/// IDE/editor implementing a vim mode).
/// - "host" plugin host, typically started by nvim
/// - "plugin" single plugin, started by nvim
/// @param methods Builtin methods in the client. For a host, this does not
/// include plugin methods which will be discovered later.
/// The key should be the method name, the values are dicts with
-/// the following (optional) keys:
+/// these (optional) keys (more keys may be added in future
+/// versions of Nvim, thus unknown keys are ignored. Clients
+/// must only use keys defined in this or later versions of
+/// Nvim):
/// - "async" if true, send as a notification. If false or unspecified,
/// use a blocking request
/// - "nargs" Number of arguments. Could be a single integer or an array
-/// two integers, minimum and maximum inclusive.
-/// Further keys might be added in later versions of nvim and unknown keys
-/// are thus ignored. Clients must only use keys defined in this or later
-/// versions of nvim!
-///
-/// @param attributes Informal attributes describing the client. Clients might
-/// define their own keys, but the following are suggested:
-/// - "website" Website of client (for instance github repository)
-/// - "license" Informal description of the license, such as "Apache 2",
-/// "GPLv3" or "MIT"
-/// - "logo" URI or path to image, preferably small logo or icon.
-/// .png or .svg format is preferred.
+/// of two integers, minimum and maximum inclusive.
+///
+/// @param attributes Arbitrary string:string map of informal client properties.
+/// Suggested keys:
+/// - "website": Client homepage URL (e.g. GitHub repository)
+/// - "license": License description ("Apache 2", "GPLv3", "MIT", …)
+/// - "logo": URI or path to image, preferably small logo or icon.
+/// .png or .svg format is preferred.
///
+/// @param[out] err Error details, if any
void nvim_set_client_info(uint64_t channel_id, String name,
Dictionary version, String type,
Dictionary methods, Dictionary attributes,
@@ -1344,15 +1409,14 @@ void nvim_set_client_info(uint64_t channel_id, String name,
/// Get information about a channel.
///
-/// @returns a Dictionary, describing a channel with the
-/// following keys:
-/// - "stream" the stream underlying the channel
+/// @returns Dictionary describing a channel, with these keys:
+/// - "stream" the stream underlying the channel
/// - "stdio" stdin and stdout of this Nvim instance
/// - "stderr" stderr of this Nvim instance
/// - "socket" TCP/IP socket or named pipe
/// - "job" job with communication over its stdio
/// - "mode" how data received on the channel is interpreted
-/// - "bytes" send and recieve raw bytes
+/// - "bytes" send and receive raw bytes
/// - "terminal" a |terminal| instance interprets ASCII sequences
/// - "rpc" |RPC| communication on the channel is active
/// - "pty" Name of pseudoterminal, if one is used (optional).
@@ -1393,13 +1457,13 @@ Array nvim_list_chans(void)
/// 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
/// @param calls an array of calls, where each call is described by an array
-/// with two elements: the request name, and an array of arguments.
-/// @param[out] err Details of a validation error of the nvim_multi_request call
-/// itself, i.e. malformed `calls` parameter. Errors from called methods will
-/// be indicated in the return value, see below.
+/// with two elements: the request name, and an array of arguments.
+/// @param[out] err Validation error details (malformed `calls` parameter),
+/// if any. Errors from batched calls are given in the return value.
///
-/// @return an array with two elements. The first is an array of return
+/// @return Array of two elements. The first is an array of return
/// values. The second is NIL if all calls succeeded. If a call resulted in
/// an error, it is a three-element array with the zero-based index of the call
/// which resulted in an error, the error type and the error message. If an
@@ -1490,9 +1554,8 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack;
/// Parse a VimL expression.
///
-/// @param[in] expr Expression to parse. Is always treated as a single line.
-/// @param[in] flags Flags:
-///
+/// @param[in] expr Expression to parse. Always treated as a single line.
+/// @param[in] flags Flags:
/// - "m" if multiple expressions in a row are allowed (only
/// the first one will be parsed),
/// - "E" if EOC tokens are not allowed (determines whether
@@ -1500,7 +1563,6 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack;
/// operator/space, though also yielding an error).
/// - "l" when needing to start parsing with lvalues for
/// ":let" or ":for".
-///
/// Common flag sets:
/// - "m" to parse like for ":echo".
/// - "E" to parse like for "<C-r>=".
@@ -1513,63 +1575,57 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack;
/// starting column and ending column (latter exclusive:
/// one should highlight region [start_col, end_col)).
///
-/// @return AST: top-level dictionary with these keys:
-///
-/// "error": Dictionary with error, present only if parser saw some
-/// error. Contains the following keys:
-///
-/// "message": String, error message in printf format, translated.
-/// Must contain exactly one "%.*s".
-/// "arg": String, error message argument.
-///
-/// "len": Amount of bytes successfully parsed. With flags equal to ""
-/// that should be equal to the length of expr string.
-///
-/// @note: “Sucessfully parsed” here means “participated in AST
-/// creation”, not “till the first error”.
-///
-/// "ast": AST, either nil or a dictionary with these keys:
-///
-/// "type": node type, one of the value names from ExprASTNodeType
-/// stringified without "kExprNode" prefix.
-/// "start": a pair [line, column] describing where node is “started”
-/// where "line" is always 0 (will not be 0 if you will be
-/// using nvim_parse_viml() on e.g. ":let", but that is not
-/// present yet). Both elements are Integers.
-/// "len": “length” of the node. This and "start" are there for
-/// debugging purposes primary (debugging parser and providing
-/// debug information).
-/// "children": a list of nodes described in top/"ast". There always
-/// is zero, one or two children, key will not be present
-/// if node has no children. Maximum number of children
-/// may be found in node_maxchildren array.
-///
-/// Local values (present only for certain nodes):
-///
-/// "scope": a single Integer, specifies scope for "Option" and
-/// "PlainIdentifier" nodes. For "Option" it is one of
-/// ExprOptScope values, for "PlainIdentifier" it is one of
-/// ExprVarScope values.
-/// "ident": identifier (without scope, if any), present for "Option",
-/// "PlainIdentifier", "PlainKey" and "Environment" nodes.
-/// "name": Integer, register name (one character) or -1. Only present
-/// for "Register" nodes.
-/// "cmp_type": String, comparison type, one of the value names from
-/// ExprComparisonType, stringified without "kExprCmp"
-/// prefix. Only present for "Comparison" nodes.
-/// "ccs_strategy": String, case comparison strategy, one of the
-/// value names from ExprCaseCompareStrategy,
-/// stringified without "kCCStrategy" prefix. Only
-/// present for "Comparison" nodes.
-/// "augmentation": String, augmentation type for "Assignment" nodes.
-/// Is either an empty string, "Add", "Subtract" or
-/// "Concat" for "=", "+=", "-=" or ".=" respectively.
-/// "invert": Boolean, true if result of comparison needs to be
-/// inverted. Only present for "Comparison" nodes.
-/// "ivalue": Integer, integer value for "Integer" nodes.
-/// "fvalue": Float, floating-point value for "Float" nodes.
-/// "svalue": String, value for "SingleQuotedString" and
-/// "DoubleQuotedString" nodes.
+/// @return
+/// - AST: top-level dictionary with these keys:
+/// - "error": Dictionary with error, present only if parser saw some
+/// error. Contains the following keys:
+/// - "message": String, error message in printf format, translated.
+/// Must contain exactly one "%.*s".
+/// - "arg": String, error message argument.
+/// - "len": Amount of bytes successfully parsed. With flags equal to ""
+/// that should be equal to the length of expr string.
+/// (“Sucessfully parsed” here means “participated in AST
+/// creation”, not “till the first error”.)
+/// - "ast": AST, either nil or a dictionary with these keys:
+/// - "type": node type, one of the value names from ExprASTNodeType
+/// stringified without "kExprNode" prefix.
+/// - "start": a pair [line, column] describing where node is "started"
+/// where "line" is always 0 (will not be 0 if you will be
+/// using nvim_parse_viml() on e.g. ":let", but that is not
+/// present yet). Both elements are Integers.
+/// - "len": “length” of the node. This and "start" are there for
+/// debugging purposes primary (debugging parser and providing
+/// debug information).
+/// - "children": a list of nodes described in top/"ast". There always
+/// is zero, one or two children, key will not be present
+/// if node has no children. Maximum number of children
+/// may be found in node_maxchildren array.
+/// - Local values (present only for certain nodes):
+/// - "scope": a single Integer, specifies scope for "Option" and
+/// "PlainIdentifier" nodes. For "Option" it is one of
+/// ExprOptScope values, for "PlainIdentifier" it is one of
+/// ExprVarScope values.
+/// - "ident": identifier (without scope, if any), present for "Option",
+/// "PlainIdentifier", "PlainKey" and "Environment" nodes.
+/// - "name": Integer, register name (one character) or -1. Only present
+/// for "Register" nodes.
+/// - "cmp_type": String, comparison type, one of the value names from
+/// ExprComparisonType, stringified without "kExprCmp"
+/// prefix. Only present for "Comparison" nodes.
+/// - "ccs_strategy": String, case comparison strategy, one of the
+/// value names from ExprCaseCompareStrategy,
+/// stringified without "kCCStrategy" prefix. Only
+/// present for "Comparison" nodes.
+/// - "augmentation": String, augmentation type for "Assignment" nodes.
+/// Is either an empty string, "Add", "Subtract" or
+/// "Concat" for "=", "+=", "-=" or ".=" respectively.
+/// - "invert": Boolean, true if result of comparison needs to be
+/// inverted. Only present for "Comparison" nodes.
+/// - "ivalue": Integer, integer value for "Integer" nodes.
+/// - "fvalue": Float, floating-point value for "Float" nodes.
+/// - "svalue": String, value for "SingleQuotedString" and
+/// "DoubleQuotedString" nodes.
+/// @param[out] err Error details, if any
Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight,
Error *err)
FUNC_API_SINCE(4) FUNC_API_ASYNC
@@ -2034,15 +2090,12 @@ Dictionary nvim__stats(void)
/// Gets a list of dictionaries representing attached UIs.
///
-/// @return Array of UI dictionaries
-///
-/// Each dictionary has the following keys:
-/// - "height" requested height of the UI
-/// - "width" requested width of the UI
-/// - "rgb" whether the UI uses rgb colors (false implies cterm colors)
-/// - "ext_..." Requested UI extensions, see |ui-options|
-/// - "chan" Channel id of remote UI (not present for TUI)
-///
+/// @return Array of UI dictionaries, each with these keys:
+/// - "height" Requested height of the UI
+/// - "width" Requested width of the UI
+/// - "rgb" true if the UI uses RGB colors (false implies |cterm-colors|)
+/// - "ext_..." Requested UI extensions, see |ui-option|
+/// - "chan" Channel id of remote UI (not present for TUI)
Array nvim_list_uis(void)
FUNC_API_SINCE(4)
{
@@ -2145,6 +2198,7 @@ Object nvim_get_proc(Integer pid, Error *err)
/// @param finish Finish the completion and dismiss the popupmenu. Implies
/// `insert`.
/// @param opts Optional parameters. Reserved for future use.
+/// @param[out] err Error details, if any
void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish,
Dictionary opts, Error *err)
FUNC_API_SINCE(6)
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index 157f73c9fa..e1c50cb89d 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -67,6 +67,10 @@ void nvim_win_set_buf(Window window, Buffer buffer, Error *err)
buffer);
}
+ // If window is not current, state logic will not validate its cursor.
+ // So do it now.
+ validate_cursor();
+
restore_win(save_curwin, save_curtab, false);
}
@@ -345,6 +349,7 @@ Object nvim_win_get_option(Window window, String name, Error *err)
/// Sets a window option value. Passing 'nil' as value deletes the option(only
/// works if there's a global fallback)
///
+/// @param channel_id
/// @param window Window handle
/// @param name Option name
/// @param value Option value
@@ -438,14 +443,16 @@ Boolean nvim_win_is_valid(Window window)
/// floating and external windows (including changing a split window to these
/// types).
///
-/// See documentation at |nvim_open_win()|, for the meaning of parameters. Pass
-/// in -1 for 'witdh' and 'height' to keep exiting size.
+/// See documentation at |nvim_open_win()|, for the meaning of parameters.
///
/// When reconfiguring a floating window, absent option keys will not be
/// changed. The following restriction apply: `row`, `col` and `relative`
/// must be reconfigured together. Only changing a subset of these is an error.
-void nvim_win_config(Window window, Integer width, Integer height,
- Dictionary options, Error *err)
+///
+/// @param window Window handle
+/// @param config Dictionary of window configuration
+/// @param[out] err Error details, if any
+void nvim_win_set_config(Window window, Dictionary config, Error *err)
FUNC_API_SINCE(6)
{
win_T *win = find_window_by_handle(window, err);
@@ -453,25 +460,67 @@ void nvim_win_config(Window window, Integer width, Integer height,
return;
}
bool new_float = !win->w_floating;
- width = width > 0 ? width: win->w_width;
- height = height > 0 ? height : win->w_height;
// reuse old values, if not overriden
- FloatConfig config = new_float ? FLOAT_CONFIG_INIT : win->w_float_config;
+ FloatConfig fconfig = new_float ? FLOAT_CONFIG_INIT : win->w_float_config;
- if (!parse_float_config(options, &config, !new_float, err)) {
+ if (!parse_float_config(config, &fconfig, !new_float, err)) {
return;
}
if (new_float) {
- if (!win_new_float(win, (int)width, (int)height, config, err)) {
+ if (!win_new_float(win, fconfig, err)) {
return;
}
redraw_later(NOT_VALID);
} else {
- win_config_float(win, (int)width, (int)height, config);
+ win_config_float(win, fconfig);
win->w_pos_changed = true;
}
}
+/// Return window configuration.
+///
+/// Return a dictionary containing the same config that can be given to
+/// |nvim_open_win()|.
+///
+/// `relative` will be an empty string for normal windows.
+///
+/// @param window Window handle
+/// @param[out] err Error details, if any
+/// @return Window configuration
+Dictionary nvim_win_get_config(Window window, Error *err)
+ FUNC_API_SINCE(6)
+{
+ Dictionary rv = ARRAY_DICT_INIT;
+
+ win_T *wp = find_window_by_handle(window, err);
+ if (!wp) {
+ return rv;
+ }
+
+ PUT(rv, "focusable", BOOLEAN_OBJ(wp->w_float_config.focusable));
+ PUT(rv, "external", BOOLEAN_OBJ(wp->w_float_config.external));
+
+ if (wp->w_floating) {
+ PUT(rv, "width", INTEGER_OBJ(wp->w_float_config.width));
+ PUT(rv, "height", INTEGER_OBJ(wp->w_float_config.height));
+ if (!wp->w_float_config.external) {
+ if (wp->w_float_config.relative == kFloatRelativeWindow) {
+ PUT(rv, "win", INTEGER_OBJ(wp->w_float_config.window));
+ }
+ PUT(rv, "anchor", STRING_OBJ(cstr_to_string(
+ float_anchor_str[wp->w_float_config.anchor])));
+ PUT(rv, "row", FLOAT_OBJ(wp->w_float_config.row));
+ PUT(rv, "col", FLOAT_OBJ(wp->w_float_config.col));
+ }
+ }
+
+ const char *rel = (wp->w_floating && !wp->w_float_config.external
+ ? float_relative_str[wp->w_float_config.relative] : "");
+ PUT(rv, "relative", STRING_OBJ(cstr_to_string(rel)));
+
+ return rv;
+}
+
/// Close a window.
///
/// This is equivalent to |:close| with count except that it takes a window id.
@@ -480,9 +529,7 @@ void nvim_win_config(Window window, Integer width, Integer height,
/// @param force Behave like `:close!` The last window of a buffer with
/// unwritten changes can be closed. The buffer will become
/// hidden, even if 'hidden' is not set.
-///
/// @param[out] err Error details, if any
-/// @return Window number
void nvim_win_close(Window window, Boolean force, Error *err)
FUNC_API_SINCE(6)
{