aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-01-25 17:57:01 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-01-25 17:57:01 +0000
commit9837de570c5972f98e74848edc97c297a13136ea (patch)
treecc948611912d116a3f98a744e690d3d7b6e2f59a /src/nvim/api
parentc367400b73d207833d51e09d663f969ffab37531 (diff)
parent3c48d3c83fc21dbc0841f9210f04bdb073d73cd1 (diff)
downloadrneovim-9837de570c5972f98e74848edc97c297a13136ea.tar.gz
rneovim-9837de570c5972f98e74848edc97c297a13136ea.tar.bz2
rneovim-9837de570c5972f98e74848edc97c297a13136ea.zip
Merge remote-tracking branch 'upstream/master' into colorcolchar
Diffstat (limited to 'src/nvim/api')
-rw-r--r--src/nvim/api/autocmd.c109
-rw-r--r--src/nvim/api/buffer.c153
-rw-r--r--src/nvim/api/buffer.h3
-rw-r--r--src/nvim/api/command.c32
-rw-r--r--src/nvim/api/deprecated.c12
-rw-r--r--src/nvim/api/extmark.c58
-rw-r--r--src/nvim/api/extmark.h3
-rw-r--r--src/nvim/api/keysets.lua98
-rw-r--r--src/nvim/api/options.c26
-rw-r--r--src/nvim/api/private/converter.c11
-rw-r--r--src/nvim/api/private/defs.h4
-rw-r--r--src/nvim/api/private/dispatch.c29
-rw-r--r--src/nvim/api/private/dispatch.h10
-rw-r--r--src/nvim/api/private/helpers.c89
-rw-r--r--src/nvim/api/private/helpers.h6
-rw-r--r--src/nvim/api/tabpage.c16
-rw-r--r--src/nvim/api/ui.c160
-rw-r--r--src/nvim/api/ui.h2
-rw-r--r--src/nvim/api/ui_events.in.h67
-rw-r--r--src/nvim/api/vim.c97
-rw-r--r--src/nvim/api/vimscript.c19
-rw-r--r--src/nvim/api/win_config.c154
-rw-r--r--src/nvim/api/window.c30
23 files changed, 705 insertions, 483 deletions
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index b5c695b9ce..931363e199 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -1,8 +1,12 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+#include <assert.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include "lauxlib.h"
#include "nvim/api/autocmd.h"
@@ -12,7 +16,12 @@
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
+#include "nvim/ex_cmds_defs.h"
+#include "nvim/globals.h"
#include "nvim/lua/executor.h"
+#include "nvim/memory.h"
+#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/autocmd.c.generated.h"
@@ -38,7 +47,7 @@ static int64_t next_autocmd_id = 1;
/// Get all autocommands that match the corresponding {opts}.
///
/// These examples will get autocommands matching ALL the given criteria:
-/// <pre>
+/// <pre>lua
/// -- Matches all criteria
/// autocommands = vim.api.nvim_get_autocmds({
/// group = "MyGroup",
@@ -352,82 +361,49 @@ cleanup:
return autocmd_list;
}
-/// Create an |autocommand|
-///
-/// The API allows for two (mutually exclusive) types of actions to be executed when the autocommand
-/// triggers: a callback function (Lua or Vimscript), or a command (like regular autocommands).
-///
-/// Example using callback:
-/// <pre>
-/// -- Lua function
-/// local myluafun = function() print("This buffer enters") end
-///
-/// -- Vimscript function name (as a string)
-/// local myvimfun = "g:MyVimFunction"
+/// Creates an |autocommand| event handler, defined by `callback` (Lua function or Vimscript
+/// function _name_ string) or `command` (Ex command string).
///
+/// Example using Lua callback:
+/// <pre>lua
/// vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, {
/// pattern = {"*.c", "*.h"},
-/// callback = myluafun, -- Or myvimfun
+/// callback = function(ev)
+/// print(string.format('event fired: %s', vim.inspect(ev)))
+/// end
/// })
/// </pre>
///
-/// Lua functions receive a table with information about the autocmd event as an argument. To use
-/// a function which itself accepts another (optional) parameter, wrap the function
-/// in a lambda:
-///
-/// <pre>
-/// -- Lua function with an optional parameter.
-/// -- The autocmd callback would pass a table as argument but this
-/// -- function expects number|nil
-/// local myluafun = function(bufnr) bufnr = bufnr or vim.api.nvim_get_current_buf() end
-///
-/// vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, {
-/// pattern = {"*.c", "*.h"},
-/// callback = function() myluafun() end,
-/// })
-/// </pre>
-///
-/// Example using command:
-/// <pre>
+/// Example using an Ex command as the handler:
+/// <pre>lua
/// vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, {
/// pattern = {"*.c", "*.h"},
/// command = "echo 'Entering a C or C++ file'",
/// })
/// </pre>
///
-/// Example values for pattern:
-/// <pre>
-/// pattern = "*.py"
-/// pattern = { "*.py", "*.pyi" }
-/// </pre>
-///
-/// Example values for event:
-/// <pre>
-/// "BufWritePre"
-/// {"CursorHold", "BufWritePre", "BufWritePost"}
+/// Note: `pattern` is NOT automatically expanded (unlike with |:autocmd|), thus names like "$HOME"
+/// and "~" must be expanded explicitly:
+/// <pre>lua
+/// pattern = vim.fn.expand("~") .. "/some/path/*.py"
/// </pre>
///
-/// @param event (string|array) The event or events to register this autocommand
-/// @param opts Dictionary of autocommand options:
-/// - group (string|integer) optional: the autocommand group name or
-/// id to match against.
-/// - pattern (string|array) optional: pattern or patterns to match
-/// against |autocmd-pattern|.
-/// - buffer (integer) optional: buffer number for buffer local autocommands
+/// @param event (string|array) Event(s) that will trigger the handler (`callback` or `command`).
+/// @param opts Options dict:
+/// - group (string|integer) optional: autocommand group name or id to match against.
+/// - pattern (string|array) optional: pattern(s) to match literally |autocmd-pattern|.
+/// - buffer (integer) optional: buffer number for buffer-local autocommands
/// |autocmd-buflocal|. Cannot be used with {pattern}.
-/// - desc (string) optional: description of the autocommand.
-/// - callback (function|string) optional: if a string, the name of a Vimscript function
-/// to call when this autocommand is triggered. Otherwise, a Lua function which is
-/// called when this autocommand is triggered. Cannot be used with {command}. Lua
-/// callbacks can return true to delete the autocommand; in addition, they accept a
-/// single table argument with the following keys:
-/// - id: (number) the autocommand id
-/// - event: (string) the name of the event that triggered the autocommand
-/// |autocmd-events|
-/// - group: (number|nil) the autocommand group id, if it exists
-/// - match: (string) the expanded value of |<amatch>|
-/// - buf: (number) the expanded value of |<abuf>|
-/// - file: (string) the expanded value of |<afile>|
+/// - desc (string) optional: description (for documentation and troubleshooting).
+/// - callback (function|string) optional: Lua function (or Vimscript function name, if
+/// string) called when the event(s) is triggered. Lua callback can return true to
+/// delete the autocommand, and receives a table argument with these keys:
+/// - id: (number) autocommand id
+/// - event: (string) name of the triggered event |autocmd-events|
+/// - group: (number|nil) autocommand group id, if any
+/// - match: (string) expanded value of |<amatch>|
+/// - buf: (number) expanded value of |<abuf>|
+/// - file: (string) expanded value of |<afile>|
/// - data: (any) arbitrary data passed to |nvim_exec_autocmds()|
/// - command (string) optional: Vim command to execute on event. Cannot be used with
/// {callback}
@@ -436,7 +412,7 @@ cleanup:
/// - nested (boolean) optional: defaults to false. Run nested
/// autocommands |autocmd-nested|.
///
-/// @return Integer id of the created autocommand.
+/// @return Autocommand id (number)
/// @see |autocommand|
/// @see |nvim_del_autocmd()|
Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autocmd) *opts,
@@ -457,8 +433,7 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
}
if (opts->callback.type != kObjectTypeNil && opts->command.type != kObjectTypeNil) {
- api_set_error(err, kErrorTypeValidation,
- "cannot pass both: 'callback' and 'command' for the same autocmd");
+ api_set_error(err, kErrorTypeValidation, "specify either 'callback' or 'command', not both");
goto cleanup;
} else if (opts->callback.type != kObjectTypeNil) {
// TODO(tjdevries): It's possible we could accept callable tables,
@@ -687,7 +662,7 @@ cleanup:
/// Create or get an autocommand group |autocmd-groups|.
///
/// To get an existing group id, do:
-/// <pre>
+/// <pre>lua
/// local id = vim.api.nvim_create_augroup("MyGroup", {
/// clear = false
/// })
@@ -965,7 +940,7 @@ static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, Ob
patlen = aucmd_pattern_length(pat);
}
} else if (v->type == kObjectTypeArray) {
- if (!check_autocmd_string_array(*patterns, "pattern", err)) {
+ if (!check_autocmd_string_array(v->data.array, "pattern", err)) {
return false;
}
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 51fedb302a..fe9e6077d6 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -3,25 +3,30 @@
// Some of this code was adapted from 'if_py_both.h' from the original
// vim source
+
+#include <assert.h>
#include <lauxlib.h>
-#include <limits.h>
#include <stdbool.h>
+#include <stddef.h>
#include <stdint.h>
-#include <stdlib.h>
+#include <string.h>
+#include "klib/kvec.h"
+#include "lua.h"
#include "nvim/api/buffer.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
+#include "nvim/ascii.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/buffer_updates.h"
#include "nvim/change.h"
#include "nvim/cursor.h"
-#include "nvim/decoration.h"
#include "nvim/drawscreen.h"
#include "nvim/ex_cmds.h"
-#include "nvim/ex_docmd.h"
#include "nvim/extmark.h"
+#include "nvim/globals.h"
#include "nvim/lua/executor.h"
#include "nvim/mapping.h"
#include "nvim/mark.h"
@@ -29,9 +34,10 @@
#include "nvim/memory.h"
#include "nvim/move.h"
#include "nvim/ops.h"
+#include "nvim/pos.h"
+#include "nvim/types.h"
#include "nvim/undo.h"
#include "nvim/vim.h"
-#include "nvim/window.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/buffer.c.generated.h"
@@ -78,7 +84,7 @@ Integer nvim_buf_line_count(Buffer buffer, Error *err)
///
/// Example (Lua): capture buffer updates in a global `events` variable
/// (use "print(vim.inspect(events))" to see its contents):
-/// <pre>
+/// <pre>lua
/// events = {}
/// vim.api.nvim_buf_attach(0, false, {
/// on_lines=function(...) table.insert(events, {...}) end})
@@ -271,6 +277,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id,
Integer start,
Integer end,
Boolean strict_indexing,
+ lua_State *lstate,
Error *err)
FUNC_API_SINCE(1)
{
@@ -300,21 +307,18 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id,
return rv;
}
- rv.size = (size_t)(end - start);
- rv.items = xcalloc(rv.size, sizeof(Object));
+ size_t size = (size_t)(end - start);
+
+ init_line_array(lstate, &rv, size);
- if (!buf_collect_lines(buf, rv.size, start,
- (channel_id != VIML_INTERNAL_CALL), &rv, err)) {
+ if (!buf_collect_lines(buf, size, (linenr_T)start, 0, (channel_id != VIML_INTERNAL_CALL), &rv,
+ lstate, err)) {
goto end;
}
end:
if (ERROR_SET(err)) {
- for (size_t i = 0; i < rv.size; i++) {
- xfree(rv.items[i].data.string.data);
- }
-
- xfree(rv.items);
+ api_free_array(rv);
rv.items = NULL;
}
@@ -790,7 +794,8 @@ early_end:
ArrayOf(String) nvim_buf_get_text(uint64_t channel_id, Buffer buffer,
Integer start_row, Integer start_col,
Integer end_row, Integer end_col,
- Dictionary opts, Error *err)
+ Dictionary opts, lua_State *lstate,
+ Error *err)
FUNC_API_SINCE(9)
{
Array rv = ARRAY_DICT_INIT;
@@ -830,33 +835,37 @@ ArrayOf(String) nvim_buf_get_text(uint64_t channel_id, Buffer buffer,
bool replace_nl = (channel_id != VIML_INTERNAL_CALL);
+ size_t size = (size_t)(end_row - start_row) + 1;
+
+ init_line_array(lstate, &rv, size);
+
if (start_row == end_row) {
- String line = buf_get_text(buf, start_row, start_col, end_col, replace_nl, err);
+ String line = buf_get_text(buf, start_row, start_col, end_col, err);
if (ERROR_SET(err)) {
- return rv;
+ goto end;
}
-
- ADD(rv, STRING_OBJ(line));
+ push_linestr(lstate, &rv, line.data, line.size, 0, replace_nl);
return rv;
}
- rv.size = (size_t)(end_row - start_row) + 1;
- rv.items = xcalloc(rv.size, sizeof(Object));
+ String str = buf_get_text(buf, start_row, start_col, MAXCOL - 1, err);
+
+ push_linestr(lstate, &rv, str.data, str.size, 0, replace_nl);
- rv.items[0] = STRING_OBJ(buf_get_text(buf, start_row, start_col, MAXCOL - 1, replace_nl, err));
if (ERROR_SET(err)) {
goto end;
}
- if (rv.size > 2) {
- Array tmp = ARRAY_DICT_INIT;
- tmp.items = &rv.items[1];
- if (!buf_collect_lines(buf, rv.size - 2, start_row + 1, replace_nl, &tmp, err)) {
+ if (size > 2) {
+ if (!buf_collect_lines(buf, size - 2, (linenr_T)start_row + 1, 1, replace_nl, &rv, lstate,
+ err)) {
goto end;
}
}
- rv.items[rv.size - 1] = STRING_OBJ(buf_get_text(buf, end_row, 0, end_col, replace_nl, err));
+ str = buf_get_text(buf, end_row, 0, end_col, err);
+ push_linestr(lstate, &rv, str.data, str.size, (int)(size - 1), replace_nl);
+
if (ERROR_SET(err)) {
goto end;
}
@@ -1390,3 +1399,91 @@ static int64_t normalize_index(buf_T *buf, int64_t index, bool end_exclusive, bo
index++;
return index;
}
+
+/// Initialise a string array either:
+/// - on the Lua stack (as a table) (if lstate is not NULL)
+/// - as an API array object (if lstate is NULL).
+///
+/// @param lstate Lua state. When NULL the Array is initialized instead.
+/// @param a Array to initialize
+/// @param size Size of array
+static inline void init_line_array(lua_State *lstate, Array *a, size_t size)
+{
+ if (lstate) {
+ lua_createtable(lstate, (int)size, 0);
+ } else {
+ a->size = size;
+ a->items = xcalloc(a->size, sizeof(Object));
+ }
+}
+
+/// Push a string onto either the Lua stack (as a table element) or an API array object.
+///
+/// For Lua, a table of the correct size must be created first.
+/// API array objects must be pre allocated.
+///
+/// @param lstate Lua state. When NULL the Array is pushed to instead.
+/// @param a Array to push onto when not using Lua
+/// @param s String to push
+/// @param len Size of string
+/// @param idx 0-based index to place s
+/// @param replace_nl Replace newlines ('\n') with null ('\0')
+static void push_linestr(lua_State *lstate, Array *a, const char *s, size_t len, int idx,
+ bool replace_nl)
+{
+ if (lstate) {
+ // Vim represents NULs as NLs
+ if (s && replace_nl && strchr(s, '\n')) {
+ char *tmp = xmemdupz(s, len);
+ strchrsub(tmp, '\n', '\0');
+ lua_pushlstring(lstate, tmp, len);
+ xfree(tmp);
+ } else {
+ lua_pushlstring(lstate, s, len);
+ }
+ lua_rawseti(lstate, -2, idx + 1);
+ } else {
+ String str = STRING_INIT;
+ if (s) {
+ str = cbuf_to_string(s, len);
+ if (replace_nl) {
+ // Vim represents NULs as NLs, but this may confuse clients.
+ strchrsub(str.data, '\n', '\0');
+ }
+ }
+
+ a->items[idx] = STRING_OBJ(str);
+ }
+}
+
+/// Collects `n` buffer lines into array `l` and/or lua_State `lstate`, optionally replacing
+/// newlines with NUL.
+///
+/// @param buf Buffer to get lines from
+/// @param n Number of lines to collect
+/// @param replace_nl Replace newlines ("\n") with NUL
+/// @param start Line number to start from
+/// @param start_idx First index to push to
+/// @param[out] l If not NULL, Lines are copied here
+/// @param[out] lstate If not NULL, Lines are pushed into a table onto the stack
+/// @param err[out] Error, if any
+/// @return true unless `err` was set
+bool buf_collect_lines(buf_T *buf, size_t n, linenr_T start, int start_idx, bool replace_nl,
+ Array *l, lua_State *lstate, Error *err)
+{
+ for (size_t i = 0; i < n; i++) {
+ linenr_T lnum = start + (linenr_T)i;
+
+ if (lnum >= MAXLNUM) {
+ if (err != NULL) {
+ api_set_error(err, kErrorTypeValidation, "Line index is too high");
+ }
+ return false;
+ }
+
+ char *bufstr = ml_get_buf(buf, lnum, false);
+ push_linestr(lstate, l, bufstr, strlen(bufstr), start_idx + (int)i, replace_nl);
+ }
+
+ return true;
+}
diff --git a/src/nvim/api/buffer.h b/src/nvim/api/buffer.h
index 1c4a93a587..0814da63cd 100644
--- a/src/nvim/api/buffer.h
+++ b/src/nvim/api/buffer.h
@@ -1,7 +1,10 @@
#ifndef NVIM_API_BUFFER_H
#define NVIM_API_BUFFER_H
+#include <lauxlib.h>
+
#include "nvim/api/private/defs.h"
+#include "nvim/buffer_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/buffer.h.generated.h"
diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c
index 8cd2c0f8b8..abd265f2cf 100644
--- a/src/nvim/api/command.c
+++ b/src/nvim/api/command.c
@@ -1,21 +1,36 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+#include <inttypes.h>
#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "klib/kvec.h"
+#include "lauxlib.h"
#include "nvim/api/command.h"
-#include "nvim/api/private/converter.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
+#include "nvim/ascii.h"
#include "nvim/autocmd.h"
+#include "nvim/buffer_defs.h"
+#include "nvim/decoration.h"
+#include "nvim/ex_cmds.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
+#include "nvim/garray.h"
+#include "nvim/globals.h"
#include "nvim/lua/executor.h"
+#include "nvim/macros.h"
+#include "nvim/mbyte.h"
+#include "nvim/memory.h"
#include "nvim/ops.h"
+#include "nvim/pos.h"
#include "nvim/regexp.h"
+#include "nvim/strings.h"
+#include "nvim/types.h"
#include "nvim/usercmd.h"
+#include "nvim/vim.h"
#include "nvim/window.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -42,7 +57,7 @@
/// Omitted if command cannot take a register.
/// - bang: (boolean) Whether command contains a |<bang>| (!) modifier.
/// - args: (array) Command arguments.
-/// - addr: (string) Value of |:command-addr|. Uses short name.
+/// - addr: (string) Value of |:command-addr|. Uses short name or "line" for -addr=lines.
/// - nargs: (string) Value of |:command-nargs|.
/// - nextcmd: (string) Next command if there are multiple commands separated by a |:bar|.
/// Empty if there isn't a next command.
@@ -645,6 +660,12 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
OBJ_TO_CMOD_FLAG(CMOD_LOCKMARKS, mods.lockmarks, false, "'mods.lockmarks'");
OBJ_TO_CMOD_FLAG(CMOD_NOSWAPFILE, mods.noswapfile, false, "'mods.noswapfile'");
+ if (cmdinfo.cmdmod.cmod_flags & CMOD_ERRSILENT) {
+ // CMOD_ERRSILENT must imply CMOD_SILENT, otherwise apply_cmdmod() and undo_cmdmod() won't
+ // work properly.
+ cmdinfo.cmdmod.cmod_flags |= CMOD_SILENT;
+ }
+
if ((cmdinfo.cmdmod.cmod_flags & CMOD_SANDBOX) && !(ea.argt & EX_SBOXOK)) {
VALIDATION_ERROR("Command cannot be run in sandbox");
}
@@ -874,7 +895,7 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin
/// {command} is the replacement text or Lua function to execute.
///
/// Example:
-/// <pre>
+/// <pre>vim
/// :call nvim_create_user_command('SayHello', 'echo "Hello world!"', {})
/// :SayHello
/// Hello world!
@@ -884,6 +905,7 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin
/// @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:
+/// - name: (string) Command name
/// - 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>|
diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c
index abaac07755..332e2b5fc3 100644
--- a/src/nvim/api/deprecated.c
+++ b/src/nvim/api/deprecated.c
@@ -1,7 +1,6 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
@@ -11,10 +10,15 @@
#include "nvim/api/extmark.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/api/vim.h"
#include "nvim/api/vimscript.h"
+#include "nvim/buffer_defs.h"
+#include "nvim/decoration.h"
#include "nvim/extmark.h"
+#include "nvim/globals.h"
#include "nvim/lua/executor.h"
+#include "nvim/memory.h"
+#include "nvim/pos.h"
+#include "nvim/types.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/deprecated.c.generated.h"
@@ -190,7 +194,7 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err)
String rv = { .size = 0 };
index = convert_index(index);
- Array slice = nvim_buf_get_lines(0, buffer, index, index + 1, true, err);
+ Array slice = nvim_buf_get_lines(0, buffer, index, index + 1, true, NULL, err);
if (!ERROR_SET(err) && slice.size) {
rv = slice.items[0].data.string;
@@ -263,7 +267,7 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
{
start = convert_index(start) + !include_start;
end = convert_index(end) + include_end;
- return nvim_buf_get_lines(0, buffer, start, end, false, err);
+ return nvim_buf_get_lines(0, buffer, start, end, false, NULL, err);
}
/// Replaces a line range on the buffer
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index 3b1b470629..ab3b3485e4 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -1,20 +1,29 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
-#include <stdlib.h>
+#include <string.h>
+#include "klib/kvec.h"
+#include "lauxlib.h"
#include "nvim/api/extmark.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
+#include "nvim/decoration.h"
#include "nvim/decoration_provider.h"
#include "nvim/drawscreen.h"
#include "nvim/extmark.h"
#include "nvim/highlight_group.h"
-#include "nvim/lua/executor.h"
+#include "nvim/mbyte.h"
#include "nvim/memline.h"
+#include "nvim/memory.h"
+#include "nvim/pos.h"
+#include "nvim/strings.h"
+#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/extmark.c.generated.h"
@@ -31,7 +40,7 @@ void api_extmark_free_all_mem(void)
map_destroy(String, handle_T)(&namespace_ids);
}
-/// Creates a new \*namespace\* or gets an existing one.
+/// Creates a new namespace or gets an existing one. \*namespace\*
///
/// Namespaces are used for buffer highlights and virtual text, see
/// |nvim_buf_add_highlight()| and |nvim_buf_set_extmark()|.
@@ -57,7 +66,7 @@ Integer nvim_create_namespace(String name)
return (Integer)id;
}
-/// Gets existing, non-anonymous namespaces.
+/// Gets existing, non-anonymous |namespace|s.
///
/// @return dict that maps from names to namespace ids.
Dictionary nvim_get_namespaces(void)
@@ -186,7 +195,7 @@ static Array extmark_to_array(const ExtmarkInfo *extmark, bool id, bool add_dict
return rv;
}
-/// Gets the position (0-indexed) of an extmark.
+/// Gets the position (0-indexed) of an |extmark|.
///
/// @param buffer Buffer handle, or 0 for current buffer
/// @param ns_id Namespace id from |nvim_create_namespace()|
@@ -240,31 +249,29 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
return extmark_to_array(&extmark, false, details);
}
-/// Gets extmarks in "traversal order" from a |charwise| region defined by
+/// Gets |extmarks| in "traversal order" from a |charwise| region defined by
/// buffer positions (inclusive, 0-indexed |api-indexing|).
///
/// Region can be given as (row,col) tuples, or valid extmark ids (whose
/// positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1)
/// respectively, thus the following are equivalent:
-///
-/// <pre>
-/// nvim_buf_get_extmarks(0, my_ns, 0, -1, {})
-/// nvim_buf_get_extmarks(0, my_ns, [0,0], [-1,-1], {})
+/// <pre>lua
+/// vim.api.nvim_buf_get_extmarks(0, my_ns, 0, -1, {})
+/// vim.api.nvim_buf_get_extmarks(0, my_ns, {0,0}, {-1,-1}, {})
/// </pre>
///
/// If `end` is less than `start`, traversal works backwards. (Useful
/// with `limit`, to get the first marks prior to a given position.)
///
/// Example:
-///
-/// <pre>
+/// <pre>lua
/// local a = vim.api
/// local pos = a.nvim_win_get_cursor(0)
/// local ns = a.nvim_create_namespace('my-plugin')
/// -- Create new extmark at line 1, column 1.
/// local m1 = a.nvim_buf_set_extmark(0, ns, 0, 0, {})
/// -- Create new extmark at line 3, column 1.
-/// local m2 = a.nvim_buf_set_extmark(0, ns, 0, 2, {})
+/// local m2 = a.nvim_buf_set_extmark(0, ns, 2, 0, {})
/// -- Get extmarks only from line 3.
/// local ms = a.nvim_buf_get_extmarks(0, ns, {2,0}, {2,0}, {})
/// -- Get all marks in this buffer + namespace.
@@ -361,7 +368,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
return rv;
}
-/// Creates or updates an extmark.
+/// Creates or updates an |extmark|.
///
/// By default a new extmark is created when no id is passed in, but it is also
/// possible to create a new mark by passing in a previously unused id or move
@@ -691,7 +698,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
}
if (opts->sign_text.type == kObjectTypeString) {
- if (!init_sign_text((char **)&decor.sign_text,
+ if (!init_sign_text(&decor.sign_text,
opts->sign_text.data.string.data)) {
api_set_error(err, kErrorTypeValidation, "sign_text is not a valid value");
goto error;
@@ -721,8 +728,12 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
bool ephemeral = false;
OPTION_TO_BOOL(ephemeral, ephemeral, false);
- OPTION_TO_BOOL(decor.spell, spell, false);
- if (decor.spell) {
+ if (opts->spell.type == kObjectTypeNil) {
+ decor.spell = kNone;
+ } else {
+ bool spell = false;
+ OPTION_TO_BOOL(spell, spell, false);
+ decor.spell = spell ? kTrue : kFalse;
has_decor = true;
}
@@ -803,7 +814,7 @@ error:
return 0;
}
-/// Removes an extmark.
+/// Removes an |extmark|.
///
/// @param buffer Buffer handle, or 0 for current buffer
/// @param ns_id Namespace id from |nvim_create_namespace()|
@@ -833,9 +844,8 @@ uint32_t src2ns(Integer *src_id)
}
if (*src_id < 0) {
return (((uint32_t)1) << 31) - 1;
- } else {
- return (uint32_t)(*src_id);
}
+ return (uint32_t)(*src_id);
}
/// Adds a highlight to buffer.
@@ -919,7 +929,7 @@ Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, In
return ns_id;
}
-/// Clears namespaced objects (highlights, extmarks, virtual text) from
+/// Clears |namespace|d objects (highlights, |extmarks|, virtual text) from
/// a region.
///
/// Lines are 0-indexed. |api-indexing| To clear the namespace in the entire
@@ -952,12 +962,12 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start,
(int)line_end - 1, MAXCOL);
}
-/// Set or change decoration provider for a namespace
+/// Set or change decoration provider for a |namespace|
///
/// This is a very general purpose interface for having lua callbacks
/// being triggered during the redraw code.
///
-/// The expected usage is to set extmarks for the currently
+/// The expected usage is to set |extmarks| for the currently
/// redrawn buffer. |nvim_buf_set_extmark()| can be called to add marks
/// on a per-window or per-lines basis. Use the `ephemeral` key to only
/// use the mark for the current screen redraw (the callback will be called
@@ -1041,7 +1051,7 @@ error:
decor_provider_clear(p);
}
-/// Gets the line and column of an extmark.
+/// Gets the line and column of an |extmark|.
///
/// Extmarks may be queried by position, name or even special names
/// in the future such as "cursor".
diff --git a/src/nvim/api/extmark.h b/src/nvim/api/extmark.h
index 74802c6efb..0a627a889c 100644
--- a/src/nvim/api/extmark.h
+++ b/src/nvim/api/extmark.h
@@ -3,7 +3,10 @@
#include "nvim/api/private/defs.h"
#include "nvim/decoration.h"
+#include "nvim/macros.h"
#include "nvim/map.h"
+#include "nvim/map_defs.h"
+#include "nvim/types.h"
EXTERN Map(String, handle_T) namespace_ids INIT(= MAP_INIT);
EXTERN handle_T next_namespace_id INIT(= 1);
diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua
index ea8949bd2c..30dcef6127 100644
--- a/src/nvim/api/keysets.lua
+++ b/src/nvim/api/keysets.lua
@@ -1,8 +1,8 @@
return {
- context = {
+ { 'context', {
"types";
- };
- set_decoration_provider = {
+ }};
+ { 'set_decoration_provider', {
"on_start";
"on_buf";
"on_win";
@@ -10,8 +10,8 @@ return {
"on_end";
"_on_hl_def";
"_on_spell_nav";
- };
- set_extmark = {
+ }};
+ { 'set_extmark', {
"id";
"end_line";
"end_row";
@@ -39,8 +39,8 @@ return {
"conceal";
"spell";
"ui_watched";
- };
- keymap = {
+ }};
+ { 'keymap', {
"noremap";
"nowait";
"silent";
@@ -50,11 +50,11 @@ return {
"callback";
"desc";
"replace_keycodes";
- };
- get_commands = {
+ }};
+ { 'get_commands', {
"builtin";
- };
- user_command = {
+ }};
+ { 'user_command', {
"addr";
"bang";
"bar";
@@ -67,8 +67,8 @@ return {
"preview";
"range";
"register";
- };
- float_config = {
+ }};
+ { 'float_config', {
"row";
"col";
"width";
@@ -81,27 +81,29 @@ return {
"focusable";
"zindex";
"border";
+ "title";
+ "title_pos";
"style";
"noautocmd";
- };
- runtime = {
+ }};
+ { 'runtime', {
"is_lua";
"do_source";
- };
- eval_statusline = {
+ }};
+ { 'eval_statusline', {
"winid";
"maxwidth";
"fillchar";
"highlights";
"use_winbar";
"use_tabline";
- };
- option = {
+ }};
+ { 'option', {
"scope";
"win";
"buf";
- };
- highlight = {
+ }};
+ { 'highlight', {
"bold";
"standout";
"strikethrough";
@@ -112,6 +114,7 @@ return {
"underdashed";
"italic";
"reverse";
+ "altfont";
"nocombine";
"default";
"cterm";
@@ -124,8 +127,10 @@ return {
"global_link";
"fallback";
"blend";
- };
- highlight_cterm = {
+ "fg_indexed";
+ "bg_indexed";
+ }};
+ { 'highlight_cterm', {
"bold";
"standout";
"strikethrough";
@@ -136,16 +141,17 @@ return {
"underdashed";
"italic";
"reverse";
+ "altfont";
"nocombine";
- };
+ }};
-- Autocmds
- clear_autocmds = {
+ { 'clear_autocmds', {
"buffer";
"event";
"group";
"pattern";
- };
- create_autocmd = {
+ }};
+ { 'create_autocmd', {
"buffer";
"callback";
"command";
@@ -154,24 +160,24 @@ return {
"nested";
"once";
"pattern";
- };
- exec_autocmds = {
+ }};
+ { 'exec_autocmds', {
"buffer";
"group";
"modeline";
"pattern";
"data";
- };
- get_autocmds = {
+ }};
+ { 'get_autocmds', {
"event";
"group";
"pattern";
"buffer";
- };
- create_augroup = {
+ }};
+ { 'create_augroup', {
"clear";
- };
- cmd = {
+ }};
+ { 'cmd', {
"cmd";
"range";
"count";
@@ -183,12 +189,12 @@ return {
"nargs";
"addr";
"nextcmd";
- };
- cmd_magic = {
+ }};
+ { 'cmd_magic', {
"file";
"bar";
- };
- cmd_mods = {
+ }};
+ { 'cmd_mods', {
"silent";
"emsg_silent";
"unsilent";
@@ -209,13 +215,15 @@ return {
"verbose";
"vertical";
"split";
- };
- cmd_mods_filter = {
+ }};
+ { 'cmd_mods_filter', {
"pattern";
"force";
- };
- cmd_opts = {
+ }};
+ { 'cmd_opts', {
"output";
- };
+ }};
+ { 'echo_opts', {
+ "verbose";
+ }};
}
-
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c
index ec1f19cf6a..bfcb99754f 100644
--- a/src/nvim/api/options.c
+++ b/src/nvim/api/options.c
@@ -1,20 +1,21 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-#include <assert.h>
#include <inttypes.h>
+#include <limits.h>
#include <stdbool.h>
-#include <stddef.h>
-#include <stdlib.h>
#include <string.h>
#include "nvim/api/options.h"
-#include "nvim/api/private/converter.h"
+#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/autocmd.h"
-#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
+#include "nvim/eval/window.h"
+#include "nvim/globals.h"
+#include "nvim/memory.h"
#include "nvim/option.h"
-#include "nvim/option_defs.h"
+#include "nvim/vim.h"
#include "nvim/window.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -256,7 +257,7 @@ void nvim_set_option(uint64_t channel_id, String name, Object value, Error *err)
/// @param name Option name
/// @param[out] err Error details, if any
/// @return Option value (global)
-Object nvim_get_option(String name, Error *err)
+Object nvim_get_option(String name, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
return get_option_from(NULL, SREQ_GLOBAL, name, err);
@@ -268,7 +269,7 @@ Object nvim_get_option(String name, Error *err)
/// @param name Option name
/// @param[out] err Error details, if any
/// @return Option value
-Object nvim_buf_get_option(Buffer buffer, String name, Error *err)
+Object nvim_buf_get_option(Buffer buffer, String name, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -306,7 +307,7 @@ void nvim_buf_set_option(uint64_t channel_id, Buffer buffer, String name, Object
/// @param name Option name
/// @param[out] err Error details, if any
/// @return Option value
-Object nvim_win_get_option(Window window, String name, Error *err)
+Object nvim_win_get_option(Window window, String name, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -346,7 +347,7 @@ void nvim_win_set_option(uint64_t channel_id, Window window, String name, Object
/// @param name The option name
/// @param[out] err Details of an error that may have occurred
/// @return the option value
-Object get_option_from(void *from, int type, String name, Error *err)
+static Object get_option_from(void *from, int type, String name, Error *err)
{
Object rv = OBJECT_INIT;
@@ -358,8 +359,7 @@ Object get_option_from(void *from, int type, String name, Error *err)
// Return values
int64_t numval;
char *stringval = NULL;
- int flags = get_option_value_strict(name.data, &numval, &stringval,
- type, from);
+ int flags = get_option_value_strict(name.data, &numval, &stringval, type, from);
if (!flags) {
api_set_error(err, kErrorTypeValidation, "Invalid option name: '%s'",
@@ -487,7 +487,7 @@ static getoption_T access_option_value(char *key, long *numval, char **stringval
bool get, Error *err)
{
if (get) {
- return get_option_value(key, numval, stringval, opt_flags);
+ return get_option_value(key, numval, stringval, NULL, opt_flags);
} else {
char *errmsg;
if ((errmsg = set_option_value(key, *numval, *stringval, opt_flags))) {
diff --git a/src/nvim/api/private/converter.c b/src/nvim/api/private/converter.c
index b6b3c83f3c..58ff552ab7 100644
--- a/src/nvim/api/private/converter.c
+++ b/src/nvim/api/private/converter.c
@@ -2,17 +2,24 @@
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <assert.h>
+#include <stdbool.h>
#include <stddef.h>
+#include <stdint.h>
#include <stdlib.h>
+#include "klib/kvec.h"
#include "nvim/api/private/converter.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/assert.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/eval/userfunc.h"
-#include "nvim/lua/converter.h"
+#include "nvim/garray.h"
#include "nvim/lua/executor.h"
+#include "nvim/memory.h"
+#include "nvim/types.h"
+#include "nvim/vim.h"
/// Helper structure for vim_to_object
typedef struct {
@@ -351,7 +358,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
}
case kObjectTypeLuaRef: {
- char *name = (char *)register_luafunc(api_new_luaref(obj.data.luaref));
+ char *name = register_luafunc(api_new_luaref(obj.data.luaref));
tv->v_type = VAR_FUNC;
tv->vval.v_string = xstrdup(name);
break;
diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h
index 2ae3ee6c7c..8acbf0d9de 100644
--- a/src/nvim/api/private/defs.h
+++ b/src/nvim/api/private/defs.h
@@ -12,7 +12,7 @@
#define ARRAY_DICT_INIT KV_INITIAL_VALUE
#define STRING_INIT { .data = NULL, .size = 0 }
#define OBJECT_INIT { .type = kObjectTypeNil }
-#define ERROR_INIT { .type = kErrorTypeNone, .msg = NULL }
+#define ERROR_INIT ((Error) { .type = kErrorTypeNone, .msg = NULL })
#define REMOTE_TYPE(type) typedef handle_T type
#define ERROR_SET(e) ((e)->type != kErrorTypeNone)
@@ -48,7 +48,7 @@ typedef enum {
/// Internal call from lua code
#define LUA_INTERNAL_CALL (VIML_INTERNAL_CALL + 1)
-static inline bool is_internal_call(const uint64_t channel_id)
+static inline bool is_internal_call(uint64_t channel_id)
REAL_FATTR_ALWAYS_INLINE REAL_FATTR_CONST;
/// Check whether call is internal
diff --git a/src/nvim/api/private/dispatch.c b/src/nvim/api/private/dispatch.c
index d6a6fc1219..f427bba00e 100644
--- a/src/nvim/api/private/dispatch.c
+++ b/src/nvim/api/private/dispatch.c
@@ -1,38 +1,11 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-#include <assert.h>
-#include <inttypes.h>
-#include <msgpack.h>
-#include <stdbool.h>
+#include <stddef.h>
-#include "nvim/api/deprecated.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/dispatch.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/log.h"
-#include "nvim/map.h"
-#include "nvim/msgpack_rpc/helpers.h"
-#include "nvim/vim.h"
-
-// ===========================================================================
-// NEW API FILES MUST GO HERE.
-//
-// When creating a new API file, you must include it here,
-// so that the dispatcher can find the C functions that you are creating!
-// ===========================================================================
-#include "nvim/api/autocmd.h"
-#include "nvim/api/buffer.h"
-#include "nvim/api/command.h"
-#include "nvim/api/extmark.h"
-#include "nvim/api/options.h"
-#include "nvim/api/tabpage.h"
-#include "nvim/api/ui.h"
-#include "nvim/api/vim.h"
-#include "nvim/api/vimscript.h"
-#include "nvim/api/win_config.h"
-#include "nvim/api/window.h"
-#include "nvim/ui_client.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/private/dispatch_wrappers.generated.h"
diff --git a/src/nvim/api/private/dispatch.h b/src/nvim/api/private/dispatch.h
index f92b205531..4ae61b2bfb 100644
--- a/src/nvim/api/private/dispatch.h
+++ b/src/nvim/api/private/dispatch.h
@@ -1,12 +1,14 @@
#ifndef NVIM_API_PRIVATE_DISPATCH_H
#define NVIM_API_PRIVATE_DISPATCH_H
+#include <stdbool.h>
+#include <stdint.h>
+
#include "nvim/api/private/defs.h"
+#include "nvim/memory.h"
+#include "nvim/types.h"
-typedef Object (*ApiDispatchWrapper)(uint64_t channel_id,
- Array args,
- Arena *arena,
- Error *error);
+typedef Object (*ApiDispatchWrapper)(uint64_t channel_id, Array args, Arena *arena, Error *error);
/// The rpc_method_handlers table, used in msgpack_rpc_dispatch(), stores
/// functions of this type.
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 73b5489d5c..519f2cc5bf 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -3,8 +3,12 @@
#include <assert.h>
#include <inttypes.h>
+#include <limits.h>
+#include <msgpack/unpack.h>
+#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -12,28 +16,23 @@
#include "nvim/api/private/converter.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/api/vim.h"
#include "nvim/ascii.h"
-#include "nvim/assert.h"
-#include "nvim/buffer.h"
-#include "nvim/charset.h"
-#include "nvim/eval.h"
+#include "nvim/buffer_defs.h"
#include "nvim/eval/typval.h"
-#include "nvim/ex_cmds_defs.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_eval.h"
-#include "nvim/extmark.h"
+#include "nvim/garray.h"
#include "nvim/highlight_group.h"
#include "nvim/lua/executor.h"
#include "nvim/map.h"
-#include "nvim/map_defs.h"
#include "nvim/mark.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/message.h"
#include "nvim/msgpack_rpc/helpers.h"
+#include "nvim/pos.h"
#include "nvim/ui.h"
#include "nvim/version.h"
-#include "nvim/vim.h"
-#include "nvim/window.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/private/funcs_metadata.generated.h"
@@ -151,7 +150,18 @@ bool try_end(Error *err)
xfree(msg);
}
} else if (did_throw) {
- api_set_error(err, kErrorTypeException, "%s", current_exception->value);
+ if (*current_exception->throw_name != NUL) {
+ if (current_exception->throw_lnum != 0) {
+ api_set_error(err, kErrorTypeException, "%s, line %" PRIdLINENR ": %s",
+ current_exception->throw_name, current_exception->throw_lnum,
+ current_exception->value);
+ } else {
+ api_set_error(err, kErrorTypeException, "%s: %s",
+ current_exception->throw_name, current_exception->value);
+ }
+ } else {
+ api_set_error(err, kErrorTypeException, "%s", current_exception->value);
+ }
discard_current_exception();
}
@@ -391,7 +401,13 @@ String cbuf_to_string(const char *buf, size_t size)
String cstrn_to_string(const char *str, size_t maxsize)
FUNC_ATTR_NONNULL_ALL
{
- return cbuf_to_string(str, STRNLEN(str, maxsize));
+ return cbuf_to_string(str, strnlen(str, maxsize));
+}
+
+String cstrn_as_string(char *str, size_t maxsize)
+ FUNC_ATTR_NONNULL_ALL
+{
+ return cbuf_as_string(str, strnlen(str, maxsize));
}
/// Creates a String using the given C string. Unlike
@@ -462,53 +478,15 @@ Array string_to_array(const String input, bool crlf)
return ret;
}
-/// Collects `n` buffer lines into array `l`, optionally replacing newlines
-/// with NUL.
-///
-/// @param buf Buffer to get lines from
-/// @param n Number of lines to collect
-/// @param replace_nl Replace newlines ("\n") with NUL
-/// @param start Line number to start from
-/// @param[out] l Lines are copied here
-/// @param err[out] Error, if any
-/// @return true unless `err` was set
-bool buf_collect_lines(buf_T *buf, size_t n, int64_t start, bool replace_nl, Array *l, Error *err)
-{
- for (size_t i = 0; i < n; i++) {
- int64_t lnum = start + (int64_t)i;
-
- if (lnum >= MAXLNUM) {
- if (err != NULL) {
- api_set_error(err, kErrorTypeValidation, "Line index is too high");
- }
- return false;
- }
-
- const char *bufstr = ml_get_buf(buf, (linenr_T)lnum, false);
- Object str = STRING_OBJ(cstr_to_string(bufstr));
-
- if (replace_nl) {
- // Vim represents NULs as NLs, but this may confuse clients.
- strchrsub(str.data.string.data, '\n', '\0');
- }
-
- l->items[i] = str;
- }
-
- return true;
-}
-
/// Returns a substring of a buffer line
///
/// @param buf Buffer handle
/// @param lnum Line number (1-based)
/// @param start_col Starting byte offset into line (0-based)
/// @param end_col Ending byte offset into line (0-based, exclusive)
-/// @param replace_nl Replace newlines ('\n') with null ('\0')
/// @param err Error object
/// @return The text between start_col and end_col on line lnum of buffer buf
-String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col, bool replace_nl,
- Error *err)
+String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col, Error *err)
{
String rv = STRING_INIT;
@@ -517,7 +495,7 @@ String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col
return rv;
}
- const char *bufstr = ml_get_buf(buf, (linenr_T)lnum, false);
+ char *bufstr = ml_get_buf(buf, (linenr_T)lnum, false);
size_t line_length = strlen(bufstr);
start_col = start_col < 0 ? (int64_t)line_length + start_col + 1 : start_col;
@@ -537,12 +515,7 @@ String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col
return rv;
}
- rv = cstrn_to_string(&bufstr[start_col], (size_t)(end_col - start_col));
- if (replace_nl) {
- strchrsub(rv.data, '\n', '\0');
- }
-
- return rv;
+ return cstrn_as_string(&bufstr[start_col], (size_t)(end_col - start_col));
}
void api_free_string(String value)
diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h
index 65215fa8c8..ec97ba9ec6 100644
--- a/src/nvim/api/private/helpers.h
+++ b/src/nvim/api/private/helpers.h
@@ -1,11 +1,17 @@
#ifndef NVIM_API_PRIVATE_HELPERS_H
#define NVIM_API_PRIVATE_HELPERS_H
+#include <stdbool.h>
+#include <stddef.h>
+
#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/decoration.h"
#include "nvim/ex_eval_defs.h"
#include "nvim/getchar.h"
+#include "nvim/globals.h"
+#include "nvim/macros.h"
+#include "nvim/map.h"
#include "nvim/memory.h"
#include "nvim/vim.h"
diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c
index b81fc3b7d7..21eb326c3b 100644
--- a/src/nvim/api/tabpage.c
+++ b/src/nvim/api/tabpage.c
@@ -2,13 +2,14 @@
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <stdbool.h>
-#include <stdint.h>
#include <stdlib.h>
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/tabpage.h"
#include "nvim/api/vim.h"
+#include "nvim/buffer_defs.h"
+#include "nvim/globals.h"
#include "nvim/memory.h"
#include "nvim/window.h"
@@ -110,15 +111,14 @@ Window nvim_tabpage_get_win(Tabpage tabpage, Error *err)
if (tab == curtab) {
return nvim_get_current_win();
- } else {
- FOR_ALL_WINDOWS_IN_TAB(wp, tab) {
- if (wp == tab->tp_curwin) {
- return wp->handle;
- }
+ }
+ FOR_ALL_WINDOWS_IN_TAB(wp, tab) {
+ if (wp == tab->tp_curwin) {
+ return wp->handle;
}
- // There should always be a current window for a tabpage
- abort();
}
+ // There should always be a current window for a tabpage
+ abort();
}
/// Gets the tabpage number
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index e6d8cb2fdb..e67607a7e4 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -2,67 +2,41 @@
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <assert.h>
+#include <inttypes.h>
+#include <msgpack/pack.h>
#include <stdbool.h>
-#include <stddef.h>
#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/ui.h"
+#include "nvim/autocmd.h"
#include "nvim/channel.h"
-#include "nvim/cursor_shape.h"
+#include "nvim/event/loop.h"
+#include "nvim/event/wstream.h"
+#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
+#include "nvim/main.h"
#include "nvim/map.h"
+#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/msgpack_rpc/channel.h"
+#include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/option.h"
-#include "nvim/popupmenu.h"
+#include "nvim/types.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
-#include "nvim/window.h"
-
-typedef struct {
- uint64_t channel_id;
-
-#define UI_BUF_SIZE 4096 ///< total buffer size for pending msgpack data.
- /// guaranteed size available for each new event (so packing of simple events
- /// and the header of grid_line will never fail)
-#define EVENT_BUF_SIZE 256
- char buf[UI_BUF_SIZE]; ///< buffer of packed but not yet sent msgpack data
- char *buf_wptr; ///< write head of buffer
- const char *cur_event; ///< name of current event (might get multiple arglists)
- Array call_buf; ///< buffer for constructing a single arg list (max 16 elements!)
-
- // state for write_cb, while packing a single arglist to msgpack. This
- // might fail due to buffer overflow.
- size_t pack_totlen;
- bool buf_overflow;
- char *temp_buf;
-
- // We start packing the two outermost msgpack arrays before knowing the total
- // number of elements. Thus track the location where array size will need
- // to be written in the msgpack buffer, once the specific array is finished.
- char *nevents_pos;
- char *ncalls_pos;
- uint32_t nevents; ///< number of distinct events (top-level args to "redraw"
- uint32_t ncalls; ///< number of calls made to the current event (plus one for the name!)
- bool flushed_events; ///< events where sent to client without "flush" event
-
- 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;
#define BUF_POS(data) ((size_t)((data)->buf_wptr - (data)->buf))
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/ui.c.generated.h"
-# include "ui_events_remote.generated.h"
+# include "ui_events_remote.generated.h" // IWYU pragma: export
#endif
static PMap(uint64_t) connected_uis = MAP_INIT;
@@ -137,8 +111,6 @@ void remote_ui_disconnect(uint64_t channel_id)
UIData *data = ui->data;
kv_destroy(data->call_buf);
pmap_del(uint64_t)(&connected_uis, channel_id);
- xfree(data);
- ui->data = NULL; // Flag UI as "stopped".
ui_detach_impl(ui, channel_id);
xfree(ui);
}
@@ -198,32 +170,6 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
ui->pum_col = -1.0;
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;
- ui->mode_info_set = remote_ui_mode_info_set;
- ui->update_menu = remote_ui_update_menu;
- ui->busy_start = remote_ui_busy_start;
- ui->busy_stop = remote_ui_busy_stop;
- ui->mouse_on = remote_ui_mouse_on;
- ui->mouse_off = remote_ui_mouse_off;
- ui->mode_change = remote_ui_mode_change;
- ui->grid_scroll = remote_ui_grid_scroll;
- ui->hl_attr_define = remote_ui_hl_attr_define;
- ui->hl_group_set = remote_ui_hl_group_set;
- ui->raw_line = remote_ui_raw_line;
- ui->bell = remote_ui_bell;
- ui->visual_bell = remote_ui_visual_bell;
- ui->default_colors_set = remote_ui_default_colors_set;
- ui->flush = remote_ui_flush;
- ui->suspend = remote_ui_suspend;
- ui->set_title = remote_ui_set_title;
- ui->set_icon = remote_ui_set_icon;
- ui->option_set = remote_ui_option_set;
- ui->msg_set_pos = remote_ui_msg_set_pos;
- ui->event = remote_ui_event;
- ui->inspect = remote_ui_inspect;
- ui->win_viewport = remote_ui_win_viewport;
CLEAR_FIELD(ui->ui_ext);
@@ -246,7 +192,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
ui->ui_ext[kUICmdline] = true;
}
- UIData *data = xmalloc(sizeof(UIData));
+ UIData *data = ui->data;
data->channel_id = channel_id;
data->cur_event = NULL;
data->hl_id = 0;
@@ -261,7 +207,6 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
data->wildmenu_active = false;
data->call_buf = (Array)ARRAY_DICT_INIT;
kv_ensure_space(data->call_buf, 16);
- ui->data = data;
pmap_put(uint64_t)(&connected_uis, channel_id, ui);
ui_attach_impl(ui, channel_id);
@@ -277,6 +222,19 @@ void ui_attach(uint64_t channel_id, Integer width, Integer height, Boolean enabl
api_free_dictionary(opts);
}
+/// Tells the nvim server if focus was gained or lost by the GUI
+void nvim_ui_set_focus(uint64_t channel_id, Boolean gained, Error *error)
+ FUNC_API_SINCE(11) FUNC_API_REMOTE_ONLY
+{
+ if (!pmap_has(uint64_t)(&connected_uis, channel_id)) {
+ api_set_error(error, kErrorTypeException,
+ "UI not attached to channel: %" PRId64, channel_id);
+ return;
+ }
+
+ do_autocmd_focusgained((bool)gained);
+}
+
/// Deactivates UI events on the channel.
///
/// Removes the client from the list of UIs. |nvim_list_uis()|
@@ -294,6 +252,10 @@ void nvim_ui_detach(uint64_t channel_id, Error *err)
remote_ui_disconnect(channel_id);
}
+// TODO(bfredl): use me to detach a specifc ui from the server
+void remote_ui_stop(UI *ui)
+{}
+
void nvim_ui_try_resize(uint64_t channel_id, Integer width, Integer height, Error *err)
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
{
@@ -396,6 +358,24 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, Error *e
return;
}
+ if (strequal(name.data, "stdin_tty")) {
+ if (value.type != kObjectTypeBoolean) {
+ api_set_error(error, kErrorTypeValidation, "stdin_tty must be a Boolean");
+ return;
+ }
+ stdin_isatty = value.data.boolean;
+ return;
+ }
+
+ if (strequal(name.data, "stdout_tty")) {
+ if (value.type != kObjectTypeBoolean) {
+ api_set_error(error, kErrorTypeValidation, "stdout_tty must be a Boolean");
+ return;
+ }
+ stdout_isatty = value.data.boolean;
+ return;
+ }
+
// LEGACY: Deprecated option, use `ext_cmdline` instead.
bool is_popupmenu = strequal(name.data, "popupmenu_external");
@@ -647,7 +627,7 @@ static void push_call(UI *ui, const char *name, Array args)
data->ncalls++;
}
-static void remote_ui_grid_clear(UI *ui, Integer grid)
+void remote_ui_grid_clear(UI *ui, Integer grid)
{
UIData *data = ui->data;
Array args = data->call_buf;
@@ -658,7 +638,7 @@ static void remote_ui_grid_clear(UI *ui, Integer grid)
push_call(ui, name, args);
}
-static void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer height)
+void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer height)
{
UIData *data = ui->data;
Array args = data->call_buf;
@@ -671,8 +651,8 @@ static void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer h
push_call(ui, name, args);
}
-static void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integer left,
- Integer right, Integer rows, Integer cols)
+void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integer left,
+ Integer right, Integer rows, Integer cols)
{
UIData *data = ui->data;
if (ui->ui_ext[kUILinegrid]) {
@@ -708,8 +688,8 @@ static void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot
}
}
-static void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg, Integer rgb_sp,
- Integer cterm_fg, Integer cterm_bg)
+void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg, Integer rgb_sp,
+ Integer cterm_fg, Integer cterm_bg)
{
if (!ui->ui_ext[kUITermColors]) {
HL_SET_DEFAULT_COLORS(rgb_fg, rgb_bg, rgb_sp);
@@ -739,8 +719,8 @@ static void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg,
}
}
-static void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs,
- Array info)
+void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs,
+ Array info)
{
if (!ui->ui_ext[kUILinegrid]) {
return;
@@ -765,7 +745,7 @@ static void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAt
push_call(ui, "hl_attr_define", args);
}
-static void remote_ui_highlight_set(UI *ui, int id)
+void remote_ui_highlight_set(UI *ui, int id)
{
UIData *data = ui->data;
Array args = data->call_buf;
@@ -781,7 +761,7 @@ static void remote_ui_highlight_set(UI *ui, int id)
}
/// "true" cursor used only for input focus
-static void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Integer col)
+void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Integer col)
{
if (ui->ui_ext[kUILinegrid]) {
UIData *data = ui->data;
@@ -799,7 +779,7 @@ static void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Intege
}
/// emulated cursor used both for drawing and for input focus
-static void remote_ui_cursor_goto(UI *ui, Integer row, Integer col)
+void remote_ui_cursor_goto(UI *ui, Integer row, Integer col)
{
UIData *data = ui->data;
if (data->client_row == row && data->client_col == col) {
@@ -813,7 +793,7 @@ static void remote_ui_cursor_goto(UI *ui, Integer row, Integer col)
push_call(ui, "cursor_goto", args);
}
-static void remote_ui_put(UI *ui, const char *cell)
+void remote_ui_put(UI *ui, const char *cell)
{
UIData *data = ui->data;
data->client_col++;
@@ -822,9 +802,9 @@ static void remote_ui_put(UI *ui, const char *cell)
push_call(ui, "put", args);
}
-static void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Integer endcol,
- Integer clearcol, Integer clearattr, LineFlags flags,
- const schar_T *chunk, const sattr_T *attrs)
+void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Integer endcol,
+ Integer clearcol, Integer clearattr, LineFlags flags, const schar_T *chunk,
+ const sattr_T *attrs)
{
UIData *data = ui->data;
if (ui->ui_ext[kUILinegrid]) {
@@ -845,7 +825,7 @@ static void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startc
for (size_t i = 0; i < ncells; i++) {
repeat++;
if (i == ncells - 1 || attrs[i] != attrs[i + 1]
- || strcmp(chunk[i], chunk[i + 1])) {
+ || strcmp(chunk[i], chunk[i + 1]) != 0) {
if (UI_BUF_SIZE - BUF_POS(data) < 2 * (1 + 2 + sizeof(schar_T) + 5 + 5)) {
// close to overflowing the redraw buffer. finish this event,
// flush, and start a new "grid_line" event at the current position.
@@ -916,7 +896,7 @@ static void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startc
///
/// This might happen multiple times before the actual ui_flush, if the
/// total redraw size is large!
-static void remote_ui_flush_buf(UI *ui)
+void remote_ui_flush_buf(UI *ui)
{
UIData *data = ui->data;
if (!data->nevents_pos) {
@@ -943,7 +923,7 @@ static void remote_ui_flush_buf(UI *ui)
///
/// Clients can know this happened by a final "flush" event at the end of the
/// "redraw" batch.
-static void remote_ui_flush(UI *ui)
+void remote_ui_flush(UI *ui)
{
UIData *data = ui->data;
if (data->nevents > 0 || data->flushed_events) {
@@ -988,7 +968,7 @@ static Array translate_firstarg(UI *ui, Array args, Arena *arena)
return new_args;
}
-static void remote_ui_event(UI *ui, char *name, Array args)
+void remote_ui_event(UI *ui, char *name, Array args)
{
Arena arena = ARENA_EMPTY;
UIData *data = ui->data;
@@ -1055,7 +1035,7 @@ free_ret:
arena_mem_free(arena_finish(&arena));
}
-static void remote_ui_inspect(UI *ui, Dictionary *info)
+void remote_ui_inspect(UI *ui, Dictionary *info)
{
UIData *data = ui->data;
PUT(*info, "chan", INTEGER_OBJ((Integer)data->channel_id));
diff --git a/src/nvim/api/ui.h b/src/nvim/api/ui.h
index bc70406acb..b3fe0fa2bb 100644
--- a/src/nvim/api/ui.h
+++ b/src/nvim/api/ui.h
@@ -5,8 +5,10 @@
#include "nvim/api/private/defs.h"
#include "nvim/map.h"
+#include "nvim/ui.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/ui.h.generated.h"
+# include "ui_events_remote.h.generated.h"
#endif
#endif // NVIM_API_UI_H
diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h
index 17930dca85..a08e8dbfeb 100644
--- a/src/nvim/api/ui_events.in.h
+++ b/src/nvim/api/ui_events.in.h
@@ -31,15 +31,15 @@ void visual_bell(void)
void flush(void)
FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL;
void suspend(void)
- FUNC_API_SINCE(3) FUNC_API_BRIDGE_IMPL;
+ FUNC_API_SINCE(3);
void set_title(String title)
FUNC_API_SINCE(3);
void set_icon(String icon)
FUNC_API_SINCE(3);
void screenshot(String path)
- FUNC_API_SINCE(7) FUNC_API_REMOTE_IMPL;
+ FUNC_API_SINCE(7);
void option_set(String name, Object value)
- FUNC_API_SINCE(4) FUNC_API_BRIDGE_IMPL;
+ FUNC_API_SINCE(4);
// Stop event is not exported as such, represented by EOF in the msgpack stream.
void stop(void)
FUNC_API_NOEXPORT;
@@ -69,14 +69,13 @@ void scroll(Integer count)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
// Second revision of the grid protocol, used with ext_linegrid ui option
-void default_colors_set(Integer rgb_fg, Integer rgb_bg, Integer rgb_sp,
- Integer cterm_fg, Integer cterm_bg)
+void default_colors_set(Integer rgb_fg, Integer rgb_bg, Integer rgb_sp, Integer cterm_fg,
+ Integer cterm_bg)
FUNC_API_SINCE(4) FUNC_API_REMOTE_IMPL;
-void hl_attr_define(Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs,
- Array info)
- FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_BRIDGE_IMPL;
+void hl_attr_define(Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs, Array info)
+ FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL;
void hl_group_set(String name, Integer id)
- FUNC_API_SINCE(6) FUNC_API_BRIDGE_IMPL;
+ FUNC_API_SINCE(6) FUNC_API_CLIENT_IGNORE;
void grid_resize(Integer grid, Integer width, Integer height)
FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_COMPOSITOR_IMPL FUNC_API_CLIENT_IMPL;
void grid_clear(Integer grid)
@@ -85,8 +84,8 @@ void grid_cursor_goto(Integer grid, Integer row, Integer col)
FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_COMPOSITOR_IMPL;
void grid_line(Integer grid, Integer row, Integer col_start, Array data)
FUNC_API_SINCE(5) FUNC_API_REMOTE_ONLY FUNC_API_CLIENT_IMPL;
-void grid_scroll(Integer grid, Integer top, Integer bot,
- Integer left, Integer right, Integer rows, Integer cols)
+void grid_scroll(Integer grid, Integer top, Integer bot, Integer left, Integer right, Integer rows,
+ Integer cols)
FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_COMPOSITOR_IMPL;
void grid_destroy(Integer grid)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
@@ -94,20 +93,15 @@ void grid_destroy(Integer grid)
// For performance and simplicity, we use the dense screen representation
// in internal code, such as compositor and TUI. The remote_ui module will
// translate this in to the public grid_line format.
-void raw_line(Integer grid, Integer row, Integer startcol,
- Integer endcol, Integer clearcol, Integer clearattr,
- LineFlags flags, const schar_T *chunk, const sattr_T *attrs)
- FUNC_API_NOEXPORT FUNC_API_COMPOSITOR_IMPL;
-
-void event(char *name, Array args)
+void raw_line(Integer grid, Integer row, Integer startcol, Integer endcol, Integer clearcol,
+ Integer clearattr, LineFlags flags, const schar_T *chunk, const sattr_T *attrs)
FUNC_API_NOEXPORT FUNC_API_COMPOSITOR_IMPL;
-void win_pos(Integer grid, Window win, Integer startrow,
- Integer startcol, Integer width, Integer height)
+void win_pos(Integer grid, Window win, Integer startrow, Integer startcol, Integer width,
+ Integer height)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
-void win_float_pos(Integer grid, Window win, String anchor, Integer anchor_grid,
- Float anchor_row, Float anchor_col, Boolean focusable,
- Integer zindex)
+void win_float_pos(Integer grid, Window win, String anchor, Integer anchor_grid, Float anchor_row,
+ Float anchor_col, Boolean focusable, Integer zindex)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
void win_external_pos(Integer grid, Window win)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
@@ -115,32 +109,29 @@ void win_hide(Integer grid)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
void win_close(Integer grid)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
+
void msg_set_pos(Integer grid, Integer row, Boolean scrolled, String sep_char)
- FUNC_API_SINCE(6) FUNC_API_BRIDGE_IMPL FUNC_API_COMPOSITOR_IMPL;
+ FUNC_API_SINCE(6) FUNC_API_COMPOSITOR_IMPL FUNC_API_CLIENT_IGNORE;
-void win_viewport(Integer grid, Window win, Integer topline,
- Integer botline, Integer curline, Integer curcol,
- Integer line_count)
- FUNC_API_SINCE(7) FUNC_API_BRIDGE_IMPL;
+void win_viewport(Integer grid, Window win, Integer topline, Integer botline, Integer curline,
+ Integer curcol, Integer line_count)
+ FUNC_API_SINCE(7) FUNC_API_CLIENT_IGNORE;
-void win_extmark(Integer grid, Window win, Integer ns_id, Integer mark_id,
- Integer row, Integer col)
+void win_extmark(Integer grid, Window win, Integer ns_id, Integer mark_id, Integer row, Integer col)
FUNC_API_SINCE(10) FUNC_API_REMOTE_ONLY;
-void popupmenu_show(Array items, Integer selected,
- Integer row, Integer col, Integer grid)
+void popupmenu_show(Array items, Integer selected, Integer row, Integer col, Integer grid)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void popupmenu_hide(void)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void popupmenu_select(Integer selected)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
-void tabline_update(Tabpage current, Array tabs,
- Buffer current_buffer, Array buffers)
+void tabline_update(Tabpage current, Array tabs, Buffer current_buffer, Array buffers)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
-void cmdline_show(Array content, Integer pos, String firstc, String prompt,
- Integer indent, Integer level)
+void cmdline_show(Array content, Integer pos, String firstc, String prompt, Integer indent,
+ Integer level)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void cmdline_pos(Integer pos, Integer level)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
@@ -156,11 +147,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_IMPL FUNC_API_BRIDGE_IMPL;
+ FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void wildmenu_select(Integer selected)
- FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL FUNC_API_BRIDGE_IMPL;
+ FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void wildmenu_hide(void)
- FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL FUNC_API_BRIDGE_IMPL;
+ FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
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 fa8d26914a..a53b30dd8a 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -5,9 +5,13 @@
#include <inttypes.h>
#include <limits.h>
#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "klib/kvec.h"
+#include "lauxlib.h"
#include "nvim/api/buffer.h"
#include "nvim/api/deprecated.h"
#include "nvim/api/private/converter.h"
@@ -15,55 +19,52 @@
#include "nvim/api/private/dispatch.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
-#include "nvim/api/window.h"
#include "nvim/ascii.h"
+#include "nvim/autocmd.h"
#include "nvim/buffer.h"
-#include "nvim/buffer_defs.h"
-#include "nvim/charset.h"
+#include "nvim/channel.h"
#include "nvim/context.h"
-#include "nvim/decoration.h"
-#include "nvim/decoration_provider.h"
#include "nvim/drawscreen.h"
-#include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
-#include "nvim/eval/userfunc.h"
-#include "nvim/ex_cmds_defs.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
-#include "nvim/file_search.h"
-#include "nvim/fileio.h"
#include "nvim/getchar.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
-#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
-#include "nvim/insexpand.h"
+#include "nvim/keycodes.h"
+#include "nvim/log.h"
#include "nvim/lua/executor.h"
+#include "nvim/macros.h"
#include "nvim/mapping.h"
#include "nvim/mark.h"
+#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h"
#include "nvim/msgpack_rpc/channel.h"
-#include "nvim/msgpack_rpc/helpers.h"
+#include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/msgpack_rpc/unpacker.h"
#include "nvim/ops.h"
#include "nvim/option.h"
#include "nvim/optionstr.h"
#include "nvim/os/input.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/process.h"
#include "nvim/popupmenu.h"
+#include "nvim/pos.h"
#include "nvim/runtime.h"
#include "nvim/state.h"
#include "nvim/statusline.h"
+#include "nvim/strings.h"
+#include "nvim/terminal.h"
#include "nvim/types.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
-#include "nvim/viml/parser/expressions.h"
-#include "nvim/viml/parser/parser.h"
#include "nvim/window.h"
#define LINE_BUFFER_MIN_SIZE 4096
@@ -228,14 +229,14 @@ void nvim_set_hl_ns_fast(Integer ns_id, Error *err)
/// nvim_feedkeys().
///
/// Example:
-/// <pre>
+/// <pre>vim
/// :let key = nvim_replace_termcodes("<C-o>", v:true, v:false, v:true)
/// :call nvim_feedkeys(key, 'n', v:false)
/// </pre>
///
/// @param keys to be typed
/// @param mode behavior flags, see |feedkeys()|
-/// @param escape_ks If true, escape K_SPECIAL 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()
@@ -725,8 +726,11 @@ void nvim_set_vvar(String name, Object value, Error *err)
/// text chunk with specified highlight. `hl_group` element
/// can be omitted for no highlight.
/// @param history if true, add to |message-history|.
-/// @param opts Optional parameters. Reserved for future use.
-void nvim_echo(Array chunks, Boolean history, Dictionary opts, Error *err)
+/// @param opts Optional parameters.
+/// - verbose: Message was printed as a result of 'verbose' option
+/// if Nvim was invoked with -V3log_file, the message will be
+/// redirected to the log_file and suppressed from direct output.
+void nvim_echo(Array chunks, Boolean history, Dict(echo_opts) *opts, Error *err)
FUNC_API_SINCE(7)
{
HlMessage hl_msg = parse_hl_msg(chunks, err);
@@ -734,13 +738,19 @@ void nvim_echo(Array chunks, Boolean history, Dictionary opts, Error *err)
goto error;
}
- if (opts.size > 0) {
- api_set_error(err, kErrorTypeValidation, "opts dict isn't empty");
- goto error;
+ bool verbose = api_object_to_bool(opts->verbose, "verbose", false, err);
+
+ if (verbose) {
+ verbose_enter();
}
msg_multiattr(hl_msg, history ? "echomsg" : "echo", history);
+ if (verbose) {
+ verbose_leave();
+ verbose_stop(); // flush now
+ }
+
if (history) {
// history takes ownership
return;
@@ -1012,7 +1022,7 @@ Integer nvim_open_term(Buffer buffer, DictionaryOf(LuaRef) opts, Error *err)
return (Integer)chan->id;
}
-static void term_write(char *buf, size_t size, void *data)
+static void term_write(char *buf, size_t size, void *data) // NOLINT(readability-non-const-parameter)
{
Channel *chan = data;
LuaRef cb = chan->stream.internal.cb;
@@ -1294,7 +1304,7 @@ void nvim_unsubscribe(uint64_t channel_id, String event)
/// "#rrggbb" hexadecimal string.
///
/// Example:
-/// <pre>
+/// <pre>vim
/// :echo nvim_get_color_by_name("Pink")
/// :echo nvim_get_color_by_name("#cbcbcb")
/// </pre>
@@ -1436,12 +1446,12 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode)
/// Empty {rhs} is |<Nop>|. |keycodes| are replaced as usual.
///
/// Example:
-/// <pre>
+/// <pre>vim
/// call nvim_set_keymap('n', ' <NL>', '', {'nowait': v:true})
/// </pre>
///
/// is equivalent to:
-/// <pre>
+/// <pre>vim
/// nmap <nowait> <Space><NL> <Nop>
/// </pre>
///
@@ -1685,7 +1695,7 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *er
// error handled after loop
break;
}
- // TODO(bfredl): wastefull copy. It could be avoided to encoding to msgpack
+ // TODO(bfredl): wasteful copy. It could be avoided to encoding to msgpack
// directly here. But `result` might become invalid when next api function
// is called in the loop.
ADD_C(results, copy_object(result, arena));
@@ -1824,7 +1834,7 @@ Dictionary nvim__stats(void)
/// - "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)
+/// - "chan" |channel-id| of remote UI
Array nvim_list_uis(void)
FUNC_API_SINCE(4)
{
@@ -1908,19 +1918,20 @@ Object nvim_get_proc(Integer pid, Error *err)
return rvobj;
}
-/// Selects an item in the completion popupmenu.
+/// Selects an item in the completion popup menu.
///
-/// If |ins-completion| is not active this API call is silently ignored.
-/// Useful for an external UI using |ui-popupmenu| to control the popupmenu
-/// with the mouse. Can also be used in a mapping; use <cmd> |:map-cmd| to
-/// ensure the mapping doesn't end completion mode.
+/// If neither |ins-completion| nor |cmdline-completion| popup menu is active
+/// this API call is silently ignored.
+/// Useful for an external UI using |ui-popupmenu| to control the popup menu with the mouse.
+/// Can also be used in a mapping; use <Cmd> |:map-cmd| or a Lua mapping to ensure the mapping
+/// doesn't end completion mode.
///
-/// @param item Index (zero-based) of the item to select. Value of -1 selects
-/// nothing and restores the original text.
-/// @param insert Whether the selection should be inserted in the buffer.
-/// @param finish Finish the completion and dismiss the popupmenu. Implies
-/// `insert`.
-/// @param opts Optional parameters. Reserved for future use.
+/// @param item Index (zero-based) of the item to select. Value of -1 selects nothing
+/// and restores the original text.
+/// @param insert For |ins-completion|, whether the selection should be inserted in the buffer.
+/// Ignored for |cmdline-completion|.
+/// @param finish Finish the completion and dismiss the popup menu. 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)
@@ -2124,7 +2135,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
bool use_tabline = false;
bool highlights = false;
- if (str.size < 2 || memcmp(str.data, "%!", 2)) {
+ if (str.size < 2 || memcmp(str.data, "%!", 2) != 0) {
const char *const errmsg = check_stl_option(str.data);
if (errmsg) {
api_set_error(err, kErrorTypeValidation, "%s", errmsg);
@@ -2222,10 +2233,12 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
buf,
sizeof(buf),
str.data,
- false,
+ NULL,
+ 0,
fillchar,
maxwidth,
hltab_ptr,
+ NULL,
NULL);
PUT(result, "width", INTEGER_OBJ(width));
@@ -2258,7 +2271,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
if (sp->userhl == 0) {
grpname = get_default_stl_hl(wp, use_winbar);
} else if (sp->userhl < 0) {
- grpname = (char *)syn_id2name(-sp->userhl);
+ grpname = syn_id2name(-sp->userhl);
} else {
snprintf(user_group, sizeof(user_group), "User%d", sp->userhl);
grpname = user_group;
diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c
index 71209c9ab6..af1b23b712 100644
--- a/src/nvim/api/vimscript.c
+++ b/src/nvim/api/vimscript.c
@@ -2,26 +2,31 @@
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <assert.h>
-#include <limits.h>
-#include <stdlib.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include "klib/kvec.h"
#include "nvim/api/private/converter.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/vimscript.h"
#include "nvim/ascii.h"
-#include "nvim/autocmd.h"
+#include "nvim/buffer_defs.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/eval/userfunc.h"
#include "nvim/ex_docmd.h"
-#include "nvim/ops.h"
+#include "nvim/garray.h"
+#include "nvim/globals.h"
+#include "nvim/memory.h"
+#include "nvim/pos.h"
#include "nvim/runtime.h"
-#include "nvim/strings.h"
#include "nvim/vim.h"
#include "nvim/viml/parser/expressions.h"
#include "nvim/viml/parser/parser.h"
-#include "nvim/window.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/vimscript.c.generated.h"
@@ -532,7 +537,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E
kv_drop(ast_conv_stack, 1);
} else {
if (cur_item.ret_node_p->type == kObjectTypeNil) {
- size_t items_size = (size_t)(3 // "type", "start" and "len"
+ size_t items_size = (size_t)(3 // "type", "start" and "len" // NOLINT(bugprone-misplaced-widening-cast)
+ (node->children != NULL) // "children"
+ (node->type == kExprNodeOption
|| node->type == kExprNodePlainIdentifier) // "scope"
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index 636b9566ce..0ffeac1bff 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -1,19 +1,27 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-#include <assert.h>
#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
+#include <string.h>
+#include "klib/kvec.h"
+#include "nvim/api/extmark.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/win_config.h"
#include "nvim/ascii.h"
+#include "nvim/buffer_defs.h"
+#include "nvim/decoration.h"
#include "nvim/drawscreen.h"
+#include "nvim/extmark_defs.h"
+#include "nvim/globals.h"
+#include "nvim/grid_defs.h"
#include "nvim/highlight_group.h"
+#include "nvim/macros.h"
+#include "nvim/mbyte.h"
+#include "nvim/memory.h"
#include "nvim/option.h"
-#include "nvim/strings.h"
+#include "nvim/pos.h"
#include "nvim/syntax.h"
#include "nvim/ui.h"
#include "nvim/window.h"
@@ -47,13 +55,13 @@
/// this should not be used to specify arbitrary WM screen positions.
///
/// Example (Lua): window-relative float
-/// <pre>
+/// <pre>lua
/// vim.api.nvim_open_win(0, false,
/// {relative='win', row=3, col=3, width=12, height=3})
/// </pre>
///
/// Example (Lua): buffer-relative float (travels as buffer is scrolled)
-/// <pre>
+/// <pre>lua
/// vim.api.nvim_open_win(0, false,
/// {relative='win', width=12, height=3, bufpos={100,10}})
/// </pre>
@@ -66,6 +74,7 @@
/// - "editor" The global editor grid
/// - "win" Window given by the `win` field, or current window.
/// - "cursor" Cursor position in current window.
+/// - "mouse" Mouse position
/// - win: |window-ID| for relative="win".
/// - anchor: Decides which corner of the float to place at (row,col):
/// - "NW" northwest (default)
@@ -106,8 +115,9 @@
/// float where the text should not be edited. Disables
/// 'number', 'relativenumber', 'cursorline', 'cursorcolumn',
/// 'foldcolumn', 'spell' and 'list' options. 'signcolumn'
-/// is changed to `auto` and 'colorcolumn' is cleared. The
-/// end-of-buffer region is hidden by setting `eob` flag of
+/// is changed to `auto` and 'colorcolumn' is cleared.
+/// 'statuscolumn' is changed to empty. The end-of-buffer
+/// region is hidden by setting `eob` flag of
/// 'fillchars' to a space char, and clearing the
/// |hl-EndOfBuffer| region in 'winhighlight'.
/// - border: Style of (optional) window border. This can either be a string
@@ -133,7 +143,12 @@
/// will only make vertical borders but not horizontal ones.
/// By default, `FloatBorder` highlight is used, which links to `WinSeparator`
/// when not defined. It could also be specified by character:
-/// [ {"+", "MyCorner"}, {"x", "MyBorder"} ].
+/// [ ["+", "MyCorner"], ["x", "MyBorder"] ].
+/// - title: Title (optional) in window border, String or list.
+/// List is [text, highlight] tuples. if is string the default
+/// highlight group is `FloatTitle`.
+/// - title_pos: Title position must set with title option.
+/// value can be of `left` `center` `right` default is left.
/// - noautocmd: If true then no buffer-related autocommand events such as
/// |BufEnter|, |BufLeave| or |BufWinEnter| may fire from
/// calling this function.
@@ -263,7 +278,7 @@ Dictionary nvim_win_get_config(Window window, Error *err)
String s = cstrn_to_string((const char *)config->border_chars[i], sizeof(schar_T));
int hi_id = config->border_hl_ids[i];
- char *hi_name = (char *)syn_id2name(hi_id);
+ char *hi_name = syn_id2name(hi_id);
if (hi_name[0]) {
ADD(tuple, STRING_OBJ(s));
ADD(tuple, STRING_OBJ(cstr_to_string((const char *)hi_name)));
@@ -273,6 +288,29 @@ Dictionary nvim_win_get_config(Window window, Error *err)
}
}
PUT(rv, "border", ARRAY_OBJ(border));
+ if (config->title) {
+ Array titles = ARRAY_DICT_INIT;
+ VirtText title_datas = config->title_chunks;
+ for (size_t i = 0; i < title_datas.size; i++) {
+ Array tuple = ARRAY_DICT_INIT;
+ ADD(tuple, CSTR_TO_OBJ((const char *)title_datas.items[i].text));
+ if (title_datas.items[i].hl_id > 0) {
+ ADD(tuple,
+ STRING_OBJ(cstr_to_string((const char *)syn_id2name(title_datas.items[i].hl_id))));
+ }
+ ADD(titles, ARRAY_OBJ(tuple));
+ }
+ PUT(rv, "title", ARRAY_OBJ(titles));
+ char *title_pos;
+ if (config->title_pos == kAlignLeft) {
+ title_pos = "left";
+ } else if (config->title_pos == kAlignCenter) {
+ title_pos = "center";
+ } else {
+ title_pos = "right";
+ }
+ PUT(rv, "title_pos", CSTR_TO_OBJ(title_pos));
+ }
}
}
@@ -312,6 +350,8 @@ static bool parse_float_relative(String relative, FloatRelative *out)
*out = kFloatRelativeWindow;
} else if (striequal(str, "cursor")) {
*out = kFloatRelativeCursor;
+ } else if (striequal(str, "mouse")) {
+ *out = kFloatRelativeMouse;
} else {
return false;
}
@@ -330,7 +370,74 @@ static bool parse_float_bufpos(Array bufpos, lpos_T *out)
return true;
}
-static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
+static void parse_border_title(Object title, Object title_pos, 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;
+ return;
+ }
+ int hl_id = syn_check_group(S_LEN("FloatTitle"));
+ kv_push(fconfig->title_chunks, ((VirtTextChunk){ .text = xstrdup(title.data.string.data),
+ .hl_id = hl_id }));
+ fconfig->title_width = (int)mb_string2cells(title.data.string.data);
+ fconfig->title = true;
+ return;
+ }
+
+ if (title.type != kObjectTypeArray) {
+ api_set_error(err, kErrorTypeValidation, "title must be string or array");
+ return;
+ }
+
+ if (title.data.array.size == 0) {
+ api_set_error(err, kErrorTypeValidation, "title cannot be an empty array");
+ return;
+ }
+
+ fconfig->title_width = 0;
+ fconfig->title_chunks = parse_virt_text(title.data.array, err, &fconfig->title_width);
+
+ fconfig->title = true;
+}
+
+static bool parse_title_pos(Object title_pos, FloatConfig *fconfig, Error *err)
+{
+ if (!HAS_KEY(title_pos)) {
+ 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;
+
+ if (strequal(pos, "left")) {
+ fconfig->title_pos = kAlignLeft;
+ } else if (strequal(pos, "center")) {
+ fconfig->title_pos = kAlignCenter;
+ } else if (strequal(pos, "right")) {
+ fconfig->title_pos = kAlignRight;
+ } else {
+ api_set_error(err, kErrorTypeValidation, "invalid title_pos value");
+ return false;
+ }
+ return true;
+}
+
+static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
{
struct {
const char *name;
@@ -414,6 +521,8 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
String str = style.data.string;
if (str.size == 0 || strequal(str.data, "none")) {
fconfig->border = false;
+ // title does not work with border equal none
+ fconfig->title = false;
return;
}
for (size_t i = 0; defaults[i].name; i++) {
@@ -603,6 +712,29 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig,
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)) {
+ // title only work with border
+ if (!HAS_KEY(config->border) && !fconfig->border) {
+ api_set_error(err, kErrorTypeException, "title requires border to be set");
+ return false;
+ }
+
+ if (fconfig->title) {
+ clear_virttext(&fconfig->title_chunks);
+ }
+ parse_border_title(config->title, config->title_pos, fconfig, err);
+ if (ERROR_SET(err)) {
+ return false;
+ }
+ }
+
if (HAS_KEY(config->border)) {
parse_border_style(config->border, fconfig, err);
if (ERROR_SET(err)) {
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index 08dcc113da..e2c234ab29 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -10,16 +10,18 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/window.h"
#include "nvim/ascii.h"
-#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/cursor.h"
#include "nvim/drawscreen.h"
+#include "nvim/eval/window.h"
#include "nvim/ex_docmd.h"
+#include "nvim/gettext.h"
#include "nvim/globals.h"
#include "nvim/lua/executor.h"
+#include "nvim/memline_defs.h"
#include "nvim/move.h"
-#include "nvim/option.h"
-#include "nvim/syntax.h"
-#include "nvim/vim.h"
+#include "nvim/pos.h"
+#include "nvim/types.h"
#include "nvim/window.h"
/// Gets the current buffer in a window
@@ -117,8 +119,13 @@ void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err)
// Make sure we stick in this column.
win->w_set_curswant = true;
- // make sure cursor is in visible range even if win != curwin
- update_topline_win(win);
+ // make sure cursor is in visible range and
+ // cursorcolumn and cursorline are updated even if win != curwin
+ switchwin_T switchwin;
+ switch_win(&switchwin, win, NULL, true);
+ update_topline(curwin);
+ validate_cursor();
+ restore_win(&switchwin, true);
redraw_later(win, UPD_VALID);
win->w_redr_status = true;
@@ -162,9 +169,11 @@ void nvim_win_set_height(Window window, Integer height, Error *err)
win_T *savewin = curwin;
curwin = win;
+ curbuf = curwin->w_buffer;
try_start();
win_setheight((int)height);
curwin = savewin;
+ curbuf = curwin->w_buffer;
try_end(err);
}
@@ -207,9 +216,11 @@ void nvim_win_set_width(Window window, Integer width, Error *err)
win_T *savewin = curwin;
curwin = win;
+ curbuf = curwin->w_buffer;
try_start();
win_setwidth((int)width);
curwin = savewin;
+ curbuf = curwin->w_buffer;
try_end(err);
}
@@ -358,11 +369,16 @@ void nvim_win_hide(Window window, Error *err)
tabpage_T *tabpage = win_find_tabpage(win);
TryState tstate;
try_enter(&tstate);
- if (tabpage == curtab) {
+
+ // Never close the autocommand window.
+ if (is_aucmd_win(win)) {
+ emsg(_(e_autocmd_close));
+ } else if (tabpage == curtab) {
win_close(win, false, false);
} else {
win_close_othertab(win, false, tabpage);
}
+
vim_ignored = try_leave(&tstate, err);
}