aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/api.txt2
-rw-r--r--runtime/doc/eval.txt16
-rw-r--r--runtime/doc/lua.txt21
-rw-r--r--runtime/doc/starting.txt3
-rw-r--r--runtime/filetype.vim3
-rw-r--r--runtime/lua/vim/shared.lua46
-rw-r--r--runtime/plugin/diagnostic.vim26
-rw-r--r--src/nvim/api/deprecated.c14
-rw-r--r--src/nvim/api/private/dispatch.c1
-rw-r--r--src/nvim/api/private/helpers.c357
-rw-r--r--src/nvim/api/ui.c3
-rw-r--r--src/nvim/api/vim.c154
-rw-r--r--src/nvim/api/win_config.c639
-rw-r--r--src/nvim/api/win_config.h11
-rw-r--r--src/nvim/api/window.c111
-rw-r--r--src/nvim/charset.c2
-rw-r--r--src/nvim/diff.c2
-rw-r--r--src/nvim/edit.c4
-rw-r--r--src/nvim/eval.c30
-rw-r--r--src/nvim/eval/encode.c5
-rw-r--r--src/nvim/eval/funcs.c6
-rw-r--r--src/nvim/eval/typval.c2
-rw-r--r--src/nvim/ex_getln.c4
-rw-r--r--src/nvim/generators/gen_api_dispatch.lua14
-rw-r--r--src/nvim/getchar.c4
-rw-r--r--src/nvim/main.c3
-rw-r--r--src/nvim/message.c2
-rw-r--r--src/nvim/os/fs.c2
-rw-r--r--src/nvim/quickfix.c2
-rw-r--r--src/nvim/runtime.c4
-rw-r--r--src/nvim/shada.c40
-rw-r--r--src/nvim/spell.c2
-rw-r--r--src/nvim/state.c5
-rw-r--r--src/nvim/syntax.c20
-rw-r--r--src/nvim/testdir/test_filetype.vim2
-rw-r--r--src/nvim/testdir/test_functions.vim38
-rw-r--r--src/nvim/testdir/test_popup.vim4
-rw-r--r--src/nvim/undo.c4
-rw-r--r--test/functional/lua/vim_spec.lua38
39 files changed, 887 insertions, 759 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index df345e4981..a8b4bc7dd2 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -1251,7 +1251,7 @@ nvim_open_term({buffer}, {opts}) *nvim_open_term()*
For instance, for a floating display, first create an empty
buffer using |nvim_create_buf()|, then display it using
|nvim_open_win()|, and then call this function. Then
- |nvim_chan_send()| cal be called immediately to process
+ |nvim_chan_send()| can be called immediately to process
sequences in a virtual terminal having the intended size.
Parameters: ~
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index d6f72b68f7..d9ecdb40de 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -3419,6 +3419,8 @@ complete_info([{what}]) *complete_info()*
"" Not in completion mode
"keyword" Keyword completion |i_CTRL-X_CTRL-N|
"ctrl_x" Just pressed CTRL-X |i_CTRL-X|
+ "scroll" Scrolling with |i_CTRL-X_CTRL-E| or
+ |i_CTRL-X_CTRL-Y|
"whole_line" Whole lines |i_CTRL-X_CTRL-L|
"files" File names |i_CTRL-X_CTRL-F|
"tags" Tags |i_CTRL-X_CTRL-]|
@@ -6863,29 +6865,31 @@ mode([expr]) Return a string that indicates the current mode.
niR Normal using |i_CTRL-O| in |Replace-mode|
niV Normal using |i_CTRL-O| in |Virtual-Replace-mode|
v Visual by character
+ vs Visual by character using |v_CTRL-O| in Select mode
V Visual by line
+ Vs Visual by line using |v_CTRL-O| in Select mode
CTRL-V Visual blockwise
+ CTRL-Vs Visual blockwise using |v_CTRL-O| in Select mode
s Select by character
S Select by line
CTRL-S Select blockwise
- vs Visual by character using |v_CTRL-O| from
- Select mode
- Vs Visual by line using |v_CTRL-O| from Select mode
- CTRL-Vs Visual blockwise using |v_CTRL-O| from Select mode
i Insert
ic Insert mode completion |compl-generic|
ix Insert mode |i_CTRL-X| completion
R Replace |R|
Rc Replace mode completion |compl-generic|
- Rv Virtual Replace |gR|
Rx Replace mode |i_CTRL-X| completion
+ Rv Virtual Replace |gR|
+ Rvc Virtual Replace mode completion |compl-generic|
+ Rvx Virtual Replace mode |i_CTRL-X| completion
c Command-line editing
cv Vim Ex mode |Q| or |gQ|
r Hit-enter prompt
rm The -- more -- prompt
- r? |:confirm| query of some sort
+ r? A |:confirm| query of some sort
! Shell or external command is executing
t Terminal mode: keys go to the job
+
This is useful in the 'statusline' option or when used
with |remote_expr()| In most other places it always returns
"c" or "n".
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 22e323baa7..f6daa70b4c 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -1373,20 +1373,25 @@ pesc({s}) *vim.pesc()*
See also: ~
https://github.com/rxi/lume
-split({s}, {sep}, {plain}) *vim.split()*
+split({s}, {sep}, {kwargs}) *vim.split()*
Splits a string at each instance of a separator.
Examples: >
- split(":aa::b:", ":") --> {'','aa','','b',''}
- split("axaby", "ab?") --> {'','x','y'}
- split(x*yz*o, "*", true) --> {'x','yz','o'}
+
+ split(":aa::b:", ":") --> {'','aa','','b',''}
+ split("axaby", "ab?") --> {'','x','y'}
+ split("x*yz*o", "*", {plain=true}) --> {'x','yz','o'}
+ split("|x|y|z|", "|", {trimempty=true}) --> {'x', 'y', 'z'}
<
Parameters: ~
- {s} String to split
- {sep} Separator string or pattern
- {plain} If `true` use `sep` literally (passed to
- String.find)
+ {s} String to split
+ {sep} Separator string or pattern
+ {kwargs} Keyword arguments:
+ • plain: (boolean) If `true` use `sep` literally
+ (passed to string.find)
+ • trimempty: (boolean) If `true` remove empty
+ items from the front and back of the list
Return: ~
List-like table of the split components.
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index 87a48e6d2a..bb775ec884 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -90,10 +90,11 @@ argument.
See |info-message| about capturing the text.
*--clean*
---clean Equivalent to "-u NONE -i NONE":
+--clean Mimics a fresh install of Nvim:
- Skips initializations from files and environment variables.
- No 'shada' file is read or written.
- Excludes user directories from 'runtimepath'
+ - Loads builtin plugins, unlike "-u NONE -i NONE".
*--noplugin*
--noplugin Skip loading plugins. Resets the 'loadplugins' option.
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index 5e0c6fb32e..322215e1de 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -872,6 +872,9 @@ au BufNewFile,BufRead *.json-patch setf json
" Jupyter Notebook is also json
au BufNewFile,BufRead *.ipynb setf json
+" Other files that look like json
+au BufNewFile,BufRead .babelrc,.eslintrc,.prettierrc,.firebaserc setf json
+
" JSONC
au BufNewFile,BufRead *.jsonc setf jsonc
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 18c1e21049..b57b7ad4ad 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -98,17 +98,53 @@ end
--- <pre>
--- split(":aa::b:", ":") --> {'','aa','','b',''}
--- split("axaby", "ab?") --> {'','x','y'}
---- split(x*yz*o, "*", true) --> {'x','yz','o'}
+--- split("x*yz*o", "*", {plain=true}) --> {'x','yz','o'}
+--- split("|x|y|z|", "|", {trimempty=true}) --> {'x', 'y', 'z'}
--- </pre>
---
+---
---@see |vim.gsplit()|
---
---@param s String to split
---@param sep Separator string or pattern
----@param plain If `true` use `sep` literally (passed to String.find)
+---@param kwargs Keyword arguments:
+--- - plain: (boolean) If `true` use `sep` literally (passed to string.find)
+--- - trimempty: (boolean) If `true` remove empty items from the front
+--- and back of the list
---@returns List-like table of the split components.
-function vim.split(s,sep,plain)
- local t={} for c in vim.gsplit(s, sep, plain) do table.insert(t,c) end
+function vim.split(s, sep, kwargs)
+ local plain
+ local trimempty = false
+ if type(kwargs) == 'boolean' then
+ -- Support old signature for backward compatibility
+ plain = kwargs
+ else
+ vim.validate { kwargs = {kwargs, 't', true} }
+ kwargs = kwargs or {}
+ plain = kwargs.plain
+ trimempty = kwargs.trimempty
+ end
+
+ local t = {}
+ local skip = trimempty
+ for c in vim.gsplit(s, sep, plain) do
+ if c ~= "" then
+ skip = false
+ end
+
+ if not skip then
+ table.insert(t, c)
+ end
+ end
+
+ if trimempty then
+ for i = #t, 1, -1 do
+ if t[i] ~= "" then
+ break
+ end
+ table.remove(t, i)
+ end
+ end
+
return t
end
diff --git a/runtime/plugin/diagnostic.vim b/runtime/plugin/diagnostic.vim
deleted file mode 100644
index 2183623ac8..0000000000
--- a/runtime/plugin/diagnostic.vim
+++ /dev/null
@@ -1,26 +0,0 @@
-" :help vim.diagnostic
-
-hi default DiagnosticError ctermfg=1 guifg=Red
-hi default DiagnosticWarn ctermfg=3 guifg=Orange
-hi default DiagnosticInfo ctermfg=4 guifg=LightBlue
-hi default DiagnosticHint ctermfg=7 guifg=LightGrey
-
-hi default DiagnosticUnderlineError cterm=underline gui=underline guisp=Red
-hi default DiagnosticUnderlineWarn cterm=underline gui=underline guisp=Orange
-hi default DiagnosticUnderlineInfo cterm=underline gui=underline guisp=LightBlue
-hi default DiagnosticUnderlineHint cterm=underline gui=underline guisp=LightGrey
-
-hi default link DiagnosticVirtualTextError DiagnosticError
-hi default link DiagnosticVirtualTextWarn DiagnosticWarn
-hi default link DiagnosticVirtualTextInfo DiagnosticInfo
-hi default link DiagnosticVirtualTextHint DiagnosticHint
-
-hi default link DiagnosticFloatingError DiagnosticError
-hi default link DiagnosticFloatingWarn DiagnosticWarn
-hi default link DiagnosticFloatingInfo DiagnosticInfo
-hi default link DiagnosticFloatingHint DiagnosticHint
-
-hi default link DiagnosticSignError DiagnosticError
-hi default link DiagnosticSignWarn DiagnosticWarn
-hi default link DiagnosticSignInfo DiagnosticInfo
-hi default link DiagnosticSignHint DiagnosticHint
diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c
index 332fc0ba96..907d09e5b7 100644
--- a/src/nvim/api/deprecated.c
+++ b/src/nvim/api/deprecated.c
@@ -165,6 +165,7 @@ Integer nvim_buf_set_virtual_text(Buffer buffer, Integer src_id, Integer line, A
/// @param lines Array of lines
/// @param[out] err Error details, if any
void buffer_insert(Buffer buffer, Integer lnum, ArrayOf(String) lines, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
// "lnum" will be the index of the line after inserting,
// no matter if it is negative or not
@@ -184,6 +185,7 @@ void buffer_insert(Buffer buffer, Integer lnum, ArrayOf(String) lines, Error *er
/// @param[out] err Error details, if any
/// @return Line string
String buffer_get_line(Buffer buffer, Integer index, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
String rv = { .size = 0 };
@@ -212,6 +214,7 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err)
/// @param line Contents of the new line
/// @param[out] err Error details, if any
void buffer_set_line(Buffer buffer, Integer index, String line, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
Object l = STRING_OBJ(line);
Array array = { .items = &l, .size = 1 };
@@ -230,6 +233,7 @@ void buffer_set_line(Buffer buffer, Integer index, String line, Error *err)
/// @param index line index
/// @param[out] err Error details, if any
void buffer_del_line(Buffer buffer, Integer index, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
Array array = ARRAY_DICT_INIT;
index = convert_index(index);
@@ -255,6 +259,7 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
Boolean include_start,
Boolean include_end,
Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
start = convert_index(start) + !include_start;
end = convert_index(end) + include_end;
@@ -278,6 +283,7 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
/// @param[out] err Error details, if any
void buffer_set_line_slice(Buffer buffer, Integer start, Integer end, Boolean include_start,
Boolean include_end, ArrayOf(String) replacement, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
start = convert_index(start) + !include_start;
end = convert_index(end) + include_end;
@@ -298,6 +304,7 @@ void buffer_set_line_slice(Buffer buffer, Integer start, Integer end, Boolean in
/// @warning It may return nil if there was no previous value
/// or if previous value was `v:null`.
Object buffer_set_var(Buffer buffer, String name, Object value, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -317,6 +324,7 @@ Object buffer_set_var(Buffer buffer, String name, Object value, Error *err)
/// @param[out] err Error details, if any
/// @return Old value
Object buffer_del_var(Buffer buffer, String name, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -340,6 +348,7 @@ Object buffer_del_var(Buffer buffer, String name, Error *err)
/// @warning It may return nil if there was no previous value
/// or if previous value was `v:null`.
Object window_set_var(Window window, String name, Object value, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -359,6 +368,7 @@ Object window_set_var(Window window, String name, Object value, Error *err)
/// @param[out] err Error details, if any
/// @return Old value
Object window_del_var(Window window, String name, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -382,6 +392,7 @@ Object window_del_var(Window window, String name, Error *err)
/// @warning It may return nil if there was no previous value
/// or if previous value was `v:null`.
Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -401,6 +412,7 @@ Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err)
/// @param[out] err Error details, if any
/// @return Old value
Object tabpage_del_var(Tabpage tabpage, String name, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -417,6 +429,7 @@ Object tabpage_del_var(Tabpage tabpage, String name, Error *err)
/// 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)
+ FUNC_API_DEPRECATED_SINCE(1)
{
return dict_set_var(&globvardict, name, value, false, true, err);
}
@@ -424,6 +437,7 @@ Object vim_set_var(String name, Object value, Error *err)
/// @deprecated
/// @see nvim_del_var
Object vim_del_var(String name, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
return dict_set_var(&globvardict, name, NIL, true, true, err);
}
diff --git a/src/nvim/api/private/dispatch.c b/src/nvim/api/private/dispatch.c
index 5e93ccce17..ee0cdc4c07 100644
--- a/src/nvim/api/private/dispatch.c
+++ b/src/nvim/api/private/dispatch.c
@@ -15,6 +15,7 @@
#include "nvim/api/ui.h"
#include "nvim/api/vim.h"
#include "nvim/api/window.h"
+#include "nvim/api/win_config.h"
#include "nvim/log.h"
#include "nvim/map.h"
#include "nvim/msgpack_rpc/helpers.h"
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 24fac0a916..7b70c183c3 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -396,7 +396,7 @@ void set_option_to(uint64_t channel_id, void *to, int type, String name, Object
return;
}
- stringval = (char *)value.data.string.data;
+ stringval = value.data.string.data;
}
const sctx_T save_current_sctx = current_sctx;
@@ -1648,361 +1648,6 @@ const char *describe_ns(NS ns_id)
return "(UNKNOWN PLUGIN)";
}
-static bool parse_float_anchor(String anchor, FloatAnchor *out)
-{
- if (anchor.size == 0) {
- *out = (FloatAnchor)0;
- }
- char *str = anchor.data;
- if (striequal(str, "NW")) {
- *out = 0; // NW is the default
- } else if (striequal(str, "NE")) {
- *out = kFloatAnchorEast;
- } else if (striequal(str, "SW")) {
- *out = kFloatAnchorSouth;
- } else if (striequal(str, "SE")) {
- *out = kFloatAnchorSouth | kFloatAnchorEast;
- } else {
- return false;
- }
- return true;
-}
-
-static bool parse_float_relative(String relative, FloatRelative *out)
-{
- char *str = relative.data;
- if (striequal(str, "editor")) {
- *out = kFloatRelativeEditor;
- } else if (striequal(str, "win")) {
- *out = kFloatRelativeWindow;
- } else if (striequal(str, "cursor")) {
- *out = kFloatRelativeCursor;
- } else {
- return false;
- }
- return true;
-}
-
-static bool parse_float_bufpos(Array bufpos, lpos_T *out)
-{
- if (bufpos.size != 2
- || bufpos.items[0].type != kObjectTypeInteger
- || bufpos.items[1].type != kObjectTypeInteger) {
- return false;
- }
- out->lnum = bufpos.items[0].data.integer;
- out->col = (colnr_T)bufpos.items[1].data.integer;
- return true;
-}
-
-static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
-{
- struct {
- const char *name;
- schar_T chars[8];
- bool shadow_color;
- } defaults[] = {
- { "double", { "╔", "═", "╗", "║", "╝", "═", "╚", "║" }, false },
- { "single", { "┌", "─", "┐", "│", "┘", "─", "└", "│" }, false },
- { "shadow", { "", "", " ", " ", " ", " ", " ", "" }, true },
- { "rounded", { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, false },
- { "solid", { " ", " ", " ", " ", " ", " ", " ", " " }, false },
- { NULL, { { NUL } }, false },
- };
-
- schar_T *chars = fconfig->border_chars;
- int *hl_ids = fconfig->border_hl_ids;
-
- fconfig->border = true;
-
- if (style.type == kObjectTypeArray) {
- Array arr = style.data.array;
- size_t size = arr.size;
- if (!size || size > 8 || (size & (size-1))) {
- api_set_error(err, kErrorTypeValidation,
- "invalid number of border chars");
- return;
- }
- for (size_t i = 0; i < size; i++) {
- Object iytem = arr.items[i];
- String string;
- int hl_id = 0;
- if (iytem.type == kObjectTypeArray) {
- Array iarr = iytem.data.array;
- if (!iarr.size || iarr.size > 2) {
- api_set_error(err, kErrorTypeValidation, "invalid border char");
- return;
- }
- if (iarr.items[0].type != kObjectTypeString) {
- api_set_error(err, kErrorTypeValidation, "invalid border char");
- return;
- }
- string = iarr.items[0].data.string;
- if (iarr.size == 2) {
- hl_id = object_to_hl_id(iarr.items[1], "border char highlight", err);
- if (ERROR_SET(err)) {
- return;
- }
- }
- } else if (iytem.type == kObjectTypeString) {
- string = iytem.data.string;
- } else {
- api_set_error(err, kErrorTypeValidation, "invalid border char");
- return;
- }
- if (string.size
- && mb_string2cells_len((char_u *)string.data, string.size) > 1) {
- api_set_error(err, kErrorTypeValidation,
- "border chars must be one cell");
- return;
- }
- size_t len = MIN(string.size, sizeof(*chars)-1);
- if (len) {
- memcpy(chars[i], string.data, len);
- }
- chars[i][len] = NUL;
- hl_ids[i] = hl_id;
- }
- while (size < 8) {
- memcpy(chars+size, chars, sizeof(*chars) * size);
- memcpy(hl_ids+size, hl_ids, sizeof(*hl_ids) * size);
- size <<= 1;
- }
- if ((chars[7][0] && chars[1][0] && !chars[0][0])
- || (chars[1][0] && chars[3][0] && !chars[2][0])
- || (chars[3][0] && chars[5][0] && !chars[4][0])
- || (chars[5][0] && chars[7][0] && !chars[6][0])) {
- api_set_error(err, kErrorTypeValidation,
- "corner between used edges must be specified");
- }
- } else if (style.type == kObjectTypeString) {
- String str = style.data.string;
- if (str.size == 0 || strequal(str.data, "none")) {
- fconfig->border = false;
- return;
- }
- for (size_t i = 0; defaults[i].name; i++) {
- if (strequal(str.data, defaults[i].name)) {
- memcpy(chars, defaults[i].chars, sizeof(defaults[i].chars));
- memset(hl_ids, 0, 8 * sizeof(*hl_ids));
- if (defaults[i].shadow_color) {
- int hl_blend = SYN_GROUP_STATIC("FloatShadow");
- int hl_through = SYN_GROUP_STATIC("FloatShadowThrough");
- hl_ids[2] = hl_through;
- hl_ids[3] = hl_blend;
- hl_ids[4] = hl_blend;
- hl_ids[5] = hl_blend;
- hl_ids[6] = hl_through;
- }
- return;
- }
- }
- api_set_error(err, kErrorTypeValidation,
- "invalid border style \"%s\"", str.data);
- }
-}
-
-bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig, bool reconf, bool new_win,
- Error *err)
-{
- bool has_relative = false, relative_is_win = false;
- if (config->relative.type == kObjectTypeString) {
- // ignore empty string, to match nvim_win_get_config
- if (config->relative.data.string.size > 0) {
- if (!parse_float_relative(config->relative.data.string, &fconfig->relative)) {
- api_set_error(err, kErrorTypeValidation, "Invalid value of 'relative' key");
- return false;
- }
-
- if (!(HAS_KEY(config->row) && HAS_KEY(config->col)) && !HAS_KEY(config->bufpos)) {
- api_set_error(err, kErrorTypeValidation,
- "'relative' requires 'row'/'col' or 'bufpos'");
- return false;
- }
-
- has_relative = true;
- fconfig->external = false;
- if (fconfig->relative == kFloatRelativeWindow) {
- relative_is_win = true;
- fconfig->bufpos.lnum = -1;
- }
- }
- } else if (HAS_KEY(config->relative)) {
- api_set_error(err, kErrorTypeValidation, "'relative' key must be String");
- return false;
- }
-
- if (config->anchor.type == kObjectTypeString) {
- if (!parse_float_anchor(config->anchor.data.string, &fconfig->anchor)) {
- api_set_error(err, kErrorTypeValidation, "Invalid value of 'anchor' key");
- return false;
- }
- } else if (HAS_KEY(config->anchor)) {
- api_set_error(err, kErrorTypeValidation, "'anchor' key must be String");
- return false;
- }
-
- if (HAS_KEY(config->row)) {
- if (!has_relative) {
- api_set_error(err, kErrorTypeValidation, "non-float cannot have 'row'");
- return false;
- } else if (config->row.type == kObjectTypeInteger) {
- fconfig->row = (double)config->row.data.integer;
- } else if (config->row.type == kObjectTypeFloat) {
- fconfig->row = config->row.data.floating;
- } else {
- api_set_error(err, kErrorTypeValidation,
- "'row' key must be Integer or Float");
- return false;
- }
- }
-
- if (HAS_KEY(config->col)) {
- if (!has_relative) {
- api_set_error(err, kErrorTypeValidation, "non-float cannot have 'col'");
- return false;
- } else if (config->col.type == kObjectTypeInteger) {
- fconfig->col = (double)config->col.data.integer;
- } else if (config->col.type == kObjectTypeFloat) {
- fconfig->col = config->col.data.floating;
- } else {
- api_set_error(err, kErrorTypeValidation,
- "'col' key must be Integer or Float");
- return false;
- }
- }
-
- if (HAS_KEY(config->bufpos)) {
- if (!has_relative) {
- api_set_error(err, kErrorTypeValidation, "non-float cannot have 'bufpos'");
- return false;
- } else if (config->bufpos.type == kObjectTypeArray) {
- if (!parse_float_bufpos(config->bufpos.data.array, &fconfig->bufpos)) {
- api_set_error(err, kErrorTypeValidation, "Invalid value of 'bufpos' key");
- return false;
- }
-
- if (!HAS_KEY(config->row)) {
- fconfig->row = (fconfig->anchor & kFloatAnchorSouth) ? 0 : 1;
- }
- if (!HAS_KEY(config->col)) {
- fconfig->col = 0;
- }
- } else {
- api_set_error(err, kErrorTypeValidation, "'bufpos' key must be Array");
- return false;
- }
- }
-
- if (config->width.type == kObjectTypeInteger && config->width.data.integer > 0) {
- fconfig->width = (int)config->width.data.integer;
- } else if (HAS_KEY(config->width)) {
- api_set_error(err, kErrorTypeValidation, "'width' key must be a positive Integer");
- return false;
- } else if (!reconf) {
- api_set_error(err, kErrorTypeValidation, "Must specify 'width'");
- return false;
- }
-
- if (config->height.type == kObjectTypeInteger && config->height.data.integer > 0) {
- fconfig->height = (int)config->height.data.integer;
- } else if (HAS_KEY(config->height)) {
- api_set_error(err, kErrorTypeValidation, "'height' key must be a positive Integer");
- return false;
- } else if (!reconf) {
- api_set_error(err, kErrorTypeValidation, "Must specify 'height'");
- return false;
- }
-
- if (relative_is_win) {
- fconfig->window = curwin->handle;
- if (config->win.type == kObjectTypeInteger || config->win.type == kObjectTypeWindow) {
- if (config->win.data.integer > 0) {
- fconfig->window = (Window)config->win.data.integer;
- }
- } else if (HAS_KEY(config->win)) {
- api_set_error(err, kErrorTypeValidation, "'win' key must be Integer or Window");
- return false;
- }
- } else {
- if (HAS_KEY(config->win)) {
- api_set_error(err, kErrorTypeValidation, "'win' key is only valid with relative='win'");
- return false;
- }
- }
-
- if (HAS_KEY(config->external)) {
- fconfig->external = api_object_to_bool(config->external, "'external' key", false, err);
- if (ERROR_SET(err)) {
- return false;
- }
- if (has_relative && fconfig->external) {
- api_set_error(err, kErrorTypeValidation,
- "Only one of 'relative' and 'external' must be used");
- return false;
- }
- if (fconfig->external && !ui_has(kUIMultigrid)) {
- api_set_error(err, kErrorTypeValidation,
- "UI doesn't support external windows");
- return false;
- }
- }
-
- if (!reconf && (!has_relative && !fconfig->external)) {
- api_set_error(err, kErrorTypeValidation,
- "One of 'relative' and 'external' must be used");
- return false;
- }
-
-
- if (HAS_KEY(config->focusable)) {
- fconfig->focusable = api_object_to_bool(config->focusable, "'focusable' key", false, err);
- if (ERROR_SET(err)) {
- return false;
- }
- }
-
- if (config->zindex.type == kObjectTypeInteger && config->zindex.data.integer > 0) {
- fconfig->zindex = (int)config->zindex.data.integer;
- } else if (HAS_KEY(config->zindex)) {
- api_set_error(err, kErrorTypeValidation, "'zindex' key must be a positive Integer");
- return false;
- }
-
- if (HAS_KEY(config->border)) {
- parse_border_style(config->border, fconfig, err);
- if (ERROR_SET(err)) {
- return false;
- }
- }
-
- if (config->style.type == kObjectTypeString) {
- if (config->style.data.string.data[0] == NUL) {
- fconfig->style = kWinStyleUnused;
- } else if (striequal(config->style.data.string.data, "minimal")) {
- fconfig->style = kWinStyleMinimal;
- } else {
- api_set_error(err, kErrorTypeValidation, "Invalid value of 'style' key");
- }
- } else if (HAS_KEY(config->style)) {
- api_set_error(err, kErrorTypeValidation, "'style' key must be String");
- return false;
- }
-
- if (HAS_KEY(config->noautocmd)) {
- if (!new_win) {
- api_set_error(err, kErrorTypeValidation, "Invalid key: 'noautocmd'");
- return false;
- }
- fconfig->noautocmd = api_object_to_bool(config->noautocmd, "'noautocmd' key", false, err);
- if (ERROR_SET(err)) {
- return false;
- }
- }
-
- return true;
-}
-
bool api_dict_to_keydict(void *rv, field_hash hashy, Dictionary dict, Error *err)
{
for (size_t i = 0; i < dict.size; i++) {
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 9b200dcba2..d86aecc318 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -40,7 +40,6 @@ typedef struct {
static PMap(uint64_t) connected_uis = MAP_INIT;
void remote_ui_disconnect(uint64_t channel_id)
- FUNC_API_NOEXPORT
{
UI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
if (!ui) {
@@ -57,7 +56,6 @@ void remote_ui_disconnect(uint64_t channel_id)
/// Wait until ui has connected on stdio channel.
void remote_ui_wait_for_attach(void)
- FUNC_API_NOEXPORT
{
Channel *channel = find_channel(CHAN_STDIO);
if (!channel) {
@@ -172,6 +170,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
/// @deprecated
void ui_attach(uint64_t channel_id, Integer width, Integer height, Boolean enable_rgb, Error *err)
+ FUNC_API_DEPRECATED_SINCE(1)
{
Dictionary opts = ARRAY_DICT_INIT;
PUT(opts, "rgb", BOOLEAN_OBJ(enable_rgb));
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index f80d605d9a..45fca8b1c5 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -59,7 +59,6 @@
#endif
void api_vim_free_all_mem(void)
- FUNC_API_NOEXPORT
{
String name;
handle_T id;
@@ -264,7 +263,6 @@ void nvim__set_hl_ns(Integer ns_id, Error *err)
}
static void on_redraw_event(void **argv)
- FUNC_API_NOEXPORT
{
redraw_all_later(NOT_VALID);
}
@@ -1221,7 +1219,7 @@ fail:
/// buffer in a configured window before calling this. For instance, for a
/// floating display, first create an empty buffer using |nvim_create_buf()|,
/// then display it using |nvim_open_win()|, and then call this function.
-/// Then |nvim_chan_send()| cal be called immediately to process sequences
+/// Then |nvim_chan_send()| can be called immediately to process sequences
/// in a virtual terminal having the intended size.
///
/// @param buffer the buffer to use (expected to be empty)
@@ -1305,156 +1303,6 @@ void nvim_chan_send(Integer chan, String data, Error *err)
}
}
-/// Open a new window.
-///
-/// Currently this is used to open floating and external windows.
-/// Floats are windows that are drawn above the split layout, at some anchor
-/// position in some other window. Floats can be drawn internally or by external
-/// GUI with the |ui-multigrid| extension. External windows are only supported
-/// with multigrid GUIs, and are displayed as separate top-level windows.
-///
-/// For a general overview of floats, see |api-floatwin|.
-///
-/// Exactly one of `external` and `relative` must be specified. The `width` and
-/// `height` of the new window must be specified.
-///
-/// With relative=editor (row=0,col=0) refers to the top-left corner of the
-/// screen-grid and (row=Lines-1,col=Columns-1) refers to the bottom-right
-/// corner. Fractional values are allowed, but the builtin implementation
-/// (used by non-multigrid UIs) will always round down to nearest integer.
-///
-/// Out-of-bounds values, and configurations that make the float not fit inside
-/// the main editor, are allowed. The builtin implementation truncates values
-/// so floats are fully within the main screen grid. External GUIs
-/// could let floats hover outside of the main window like a tooltip, but
-/// this should not be used to specify arbitrary WM screen positions.
-///
-/// Example (Lua): window-relative float
-/// <pre>
-/// 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>
-/// vim.api.nvim_open_win(0, false,
-/// {relative='win', width=12, height=3, bufpos={100,10}})
-/// </pre>
-///
-/// @param buffer Buffer to display, or 0 for current buffer
-/// @param enter Enter the window (make it the current window)
-/// @param config Map defining the window configuration. Keys:
-/// - `relative`: Sets the window layout to "floating", placed at (row,col)
-/// coordinates relative to:
-/// - "editor" The global editor grid
-/// - "win" Window given by the `win` field, or current window.
-/// - "cursor" Cursor position in current window.
-/// - `win`: |window-ID| for relative="win".
-/// - `anchor`: Decides which corner of the float to place at (row,col):
-/// - "NW" northwest (default)
-/// - "NE" northeast
-/// - "SW" southwest
-/// - "SE" southeast
-/// - `width`: Window width (in character cells). Minimum of 1.
-/// - `height`: Window height (in character cells). Minimum of 1.
-/// - `bufpos`: Places float relative to buffer text (only when
-/// relative="win"). Takes a tuple of zero-indexed [line, column].
-/// `row` and `col` if given are applied relative to this
-/// position, else they default to:
-/// - `row=1` and `col=0` if `anchor` is "NW" or "NE"
-/// - `row=0` and `col=0` if `anchor` is "SW" or "SE"
-/// (thus like a tooltip near the buffer text).
-/// - `row`: Row position in units of "screen cell height", may be fractional.
-/// - `col`: Column position in units of "screen cell width", may be
-/// fractional.
-/// - `focusable`: Enable focus by user actions (wincmds, mouse events).
-/// Defaults to true. Non-focusable windows can be entered by
-/// |nvim_set_current_win()|.
-/// - `external`: GUI should display the window as an external
-/// top-level window. Currently accepts no other positioning
-/// configuration together with this.
-/// - `zindex`: Stacking order. floats with higher `zindex` go on top on
-/// floats with lower indices. Must be larger than zero. The
-/// following screen elements have hard-coded z-indices:
-/// - 100: insert completion popupmenu
-/// - 200: message scrollback
-/// - 250: cmdline completion popupmenu (when wildoptions+=pum)
-/// The default value for floats are 50. In general, values below 100 are
-/// recommended, unless there is a good reason to overshadow builtin
-/// elements.
-/// - `style`: Configure the appearance of the window. Currently only takes
-/// one non-empty value:
-/// - "minimal" Nvim will display the window with many UI options
-/// disabled. This is useful when displaying a temporary
-/// 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
-/// 'fillchars' to a space char, and clearing the
-/// |EndOfBuffer| region in 'winhighlight'.
-/// - `border`: Style of (optional) window border. This can either be a string
-/// or an array. The string values are
-/// - "none": No border (default).
-/// - "single": A single line box.
-/// - "double": A double line box.
-/// - "rounded": Like "single", but with rounded corners ("╭" etc.).
-/// - "solid": Adds padding by a single whitespace cell.
-/// - "shadow": A drop shadow effect by blending with the background.
-/// - If it is an array, it should have a length of eight or any divisor of
-/// eight. The array will specifify the eight chars building up the border
-/// in a clockwise fashion starting with the top-left corner. As an
-/// example, the double box style could be specified as
-/// [ "╔", "═" ,"╗", "║", "╝", "═", "╚", "║" ].
-/// If the number of chars are less than eight, they will be repeated. Thus
-/// an ASCII border could be specified as
-/// [ "/", "-", "\\", "|" ],
-/// or all chars the same as
-/// [ "x" ].
-/// An empty string can be used to turn off a specific border, for instance,
-/// [ "", "", "", ">", "", "", "", "<" ]
-/// will only make vertical borders but not horizontal ones.
-/// By default, `FloatBorder` highlight is used, which links to `VertSplit`
-/// when not defined. It could also be specified by character:
-/// [ {"+", "MyCorner"}, {"x", "MyBorder"} ].
-/// - `noautocmd`: If true then no buffer-related autocommand events such as
-/// |BufEnter|, |BufLeave| or |BufWinEnter| may fire from
-/// calling this function.
-///
-/// @param[out] err Error details, if any
-///
-/// @return Window handle, or 0 on error
-Window nvim_open_win(Buffer buffer, Boolean enter, Dict(float_config) *config, Error *err)
- FUNC_API_SINCE(6)
- FUNC_API_CHECK_TEXTLOCK
-{
- FloatConfig fconfig = FLOAT_CONFIG_INIT;
- if (!parse_float_config(config, &fconfig, false, true, err)) {
- return 0;
- }
- win_T *wp = win_new_float(NULL, fconfig, err);
- if (!wp) {
- return 0;
- }
- if (enter) {
- win_enter(wp, false);
- }
- // autocmds in win_enter or win_set_buf below may close the window
- if (win_valid(wp) && buffer > 0) {
- win_set_buf(wp->handle, buffer, fconfig.noautocmd, err);
- }
- if (!win_valid(wp)) {
- api_set_error(err, kErrorTypeException, "Window was closed immediately");
- return 0;
- }
-
- if (fconfig.style == kWinStyleMinimal) {
- win_set_minimal_style(wp);
- didset_window_options(wp);
- }
- return wp->handle;
-}
-
/// Gets the current list of tabpage handles.
///
/// @return List of tabpage handles
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
new file mode 100644
index 0000000000..d82e7e8a03
--- /dev/null
+++ b/src/nvim/api/win_config.c
@@ -0,0 +1,639 @@
+// 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 "nvim/api/private/defs.h"
+#include "nvim/api/private/helpers.h"
+#include "nvim/api/win_config.h"
+#include "nvim/ascii.h"
+#include "nvim/option.h"
+#include "nvim/screen.h"
+#include "nvim/strings.h"
+#include "nvim/syntax.h"
+#include "nvim/ui.h"
+#include "nvim/window.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "api/win_config.c.generated.h"
+#endif
+
+
+/// Open a new window.
+///
+/// Currently this is used to open floating and external windows.
+/// Floats are windows that are drawn above the split layout, at some anchor
+/// position in some other window. Floats can be drawn internally or by external
+/// GUI with the |ui-multigrid| extension. External windows are only supported
+/// with multigrid GUIs, and are displayed as separate top-level windows.
+///
+/// For a general overview of floats, see |api-floatwin|.
+///
+/// Exactly one of `external` and `relative` must be specified. The `width` and
+/// `height` of the new window must be specified.
+///
+/// With relative=editor (row=0,col=0) refers to the top-left corner of the
+/// screen-grid and (row=Lines-1,col=Columns-1) refers to the bottom-right
+/// corner. Fractional values are allowed, but the builtin implementation
+/// (used by non-multigrid UIs) will always round down to nearest integer.
+///
+/// Out-of-bounds values, and configurations that make the float not fit inside
+/// the main editor, are allowed. The builtin implementation truncates values
+/// so floats are fully within the main screen grid. External GUIs
+/// could let floats hover outside of the main window like a tooltip, but
+/// this should not be used to specify arbitrary WM screen positions.
+///
+/// Example (Lua): window-relative float
+/// <pre>
+/// 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>
+/// vim.api.nvim_open_win(0, false,
+/// {relative='win', width=12, height=3, bufpos={100,10}})
+/// </pre>
+///
+/// @param buffer Buffer to display, or 0 for current buffer
+/// @param enter Enter the window (make it the current window)
+/// @param config Map defining the window configuration. Keys:
+/// - `relative`: Sets the window layout to "floating", placed at (row,col)
+/// coordinates relative to:
+/// - "editor" The global editor grid
+/// - "win" Window given by the `win` field, or current window.
+/// - "cursor" Cursor position in current window.
+/// - `win`: |window-ID| for relative="win".
+/// - `anchor`: Decides which corner of the float to place at (row,col):
+/// - "NW" northwest (default)
+/// - "NE" northeast
+/// - "SW" southwest
+/// - "SE" southeast
+/// - `width`: Window width (in character cells). Minimum of 1.
+/// - `height`: Window height (in character cells). Minimum of 1.
+/// - `bufpos`: Places float relative to buffer text (only when
+/// relative="win"). Takes a tuple of zero-indexed [line, column].
+/// `row` and `col` if given are applied relative to this
+/// position, else they default to:
+/// - `row=1` and `col=0` if `anchor` is "NW" or "NE"
+/// - `row=0` and `col=0` if `anchor` is "SW" or "SE"
+/// (thus like a tooltip near the buffer text).
+/// - `row`: Row position in units of "screen cell height", may be fractional.
+/// - `col`: Column position in units of "screen cell width", may be
+/// fractional.
+/// - `focusable`: Enable focus by user actions (wincmds, mouse events).
+/// Defaults to true. Non-focusable windows can be entered by
+/// |nvim_set_current_win()|.
+/// - `external`: GUI should display the window as an external
+/// top-level window. Currently accepts no other positioning
+/// configuration together with this.
+/// - `zindex`: Stacking order. floats with higher `zindex` go on top on
+/// floats with lower indices. Must be larger than zero. The
+/// following screen elements have hard-coded z-indices:
+/// - 100: insert completion popupmenu
+/// - 200: message scrollback
+/// - 250: cmdline completion popupmenu (when wildoptions+=pum)
+/// The default value for floats are 50. In general, values below 100 are
+/// recommended, unless there is a good reason to overshadow builtin
+/// elements.
+/// - `style`: Configure the appearance of the window. Currently only takes
+/// one non-empty value:
+/// - "minimal" Nvim will display the window with many UI options
+/// disabled. This is useful when displaying a temporary
+/// 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
+/// 'fillchars' to a space char, and clearing the
+/// |EndOfBuffer| region in 'winhighlight'.
+/// - `border`: Style of (optional) window border. This can either be a string
+/// or an array. The string values are
+/// - "none": No border (default).
+/// - "single": A single line box.
+/// - "double": A double line box.
+/// - "rounded": Like "single", but with rounded corners ("╭" etc.).
+/// - "solid": Adds padding by a single whitespace cell.
+/// - "shadow": A drop shadow effect by blending with the background.
+/// - If it is an array, it should have a length of eight or any divisor of
+/// eight. The array will specifify the eight chars building up the border
+/// in a clockwise fashion starting with the top-left corner. As an
+/// example, the double box style could be specified as
+/// [ "╔", "═" ,"╗", "║", "╝", "═", "╚", "║" ].
+/// If the number of chars are less than eight, they will be repeated. Thus
+/// an ASCII border could be specified as
+/// [ "/", "-", "\\", "|" ],
+/// or all chars the same as
+/// [ "x" ].
+/// An empty string can be used to turn off a specific border, for instance,
+/// [ "", "", "", ">", "", "", "", "<" ]
+/// will only make vertical borders but not horizontal ones.
+/// By default, `FloatBorder` highlight is used, which links to `VertSplit`
+/// when not defined. It could also be specified by character:
+/// [ {"+", "MyCorner"}, {"x", "MyBorder"} ].
+/// - `noautocmd`: If true then no buffer-related autocommand events such as
+/// |BufEnter|, |BufLeave| or |BufWinEnter| may fire from
+/// calling this function.
+///
+/// @param[out] err Error details, if any
+///
+/// @return Window handle, or 0 on error
+Window nvim_open_win(Buffer buffer, Boolean enter, Dict(float_config) *config, Error *err)
+ FUNC_API_SINCE(6)
+ FUNC_API_CHECK_TEXTLOCK
+{
+ FloatConfig fconfig = FLOAT_CONFIG_INIT;
+ if (!parse_float_config(config, &fconfig, false, true, err)) {
+ return 0;
+ }
+ win_T *wp = win_new_float(NULL, fconfig, err);
+ if (!wp) {
+ return 0;
+ }
+ if (enter) {
+ win_enter(wp, false);
+ }
+ // autocmds in win_enter or win_set_buf below may close the window
+ if (win_valid(wp) && buffer > 0) {
+ win_set_buf(wp->handle, buffer, fconfig.noautocmd, err);
+ }
+ if (!win_valid(wp)) {
+ api_set_error(err, kErrorTypeException, "Window was closed immediately");
+ return 0;
+ }
+
+ if (fconfig.style == kWinStyleMinimal) {
+ win_set_minimal_style(wp);
+ didset_window_options(wp);
+ }
+ return wp->handle;
+}
+
+/// Configures window layout. Currently only for floating and external windows
+/// (including changing a split window to those layouts).
+///
+/// When reconfiguring a floating window, absent option keys will not be
+/// changed. `row`/`col` and `relative` must be reconfigured together.
+///
+/// @see |nvim_open_win()|
+///
+/// @param window Window handle, or 0 for current window
+/// @param config Map defining the window configuration,
+/// see |nvim_open_win()|
+/// @param[out] err Error details, if any
+void nvim_win_set_config(Window window, Dict(float_config) *config, Error *err)
+ FUNC_API_SINCE(6)
+{
+ win_T *win = find_window_by_handle(window, err);
+ if (!win) {
+ return;
+ }
+ bool new_float = !win->w_floating;
+ // reuse old values, if not overridden
+ FloatConfig fconfig = new_float ? FLOAT_CONFIG_INIT : win->w_float_config;
+
+ if (!parse_float_config(config, &fconfig, !new_float, false, err)) {
+ return;
+ }
+ if (new_float) {
+ if (!win_new_float(win, fconfig, err)) {
+ return;
+ }
+ redraw_later(win, NOT_VALID);
+ } else {
+ win_config_float(win, fconfig);
+ win->w_pos_changed = true;
+ }
+ if (fconfig.style == kWinStyleMinimal) {
+ win_set_minimal_style(win);
+ didset_window_options(win);
+ }
+}
+
+/// Gets window configuration.
+///
+/// The returned value may be given to |nvim_open_win()|.
+///
+/// `relative` is empty for normal windows.
+///
+/// @param window Window handle, or 0 for current window
+/// @param[out] err Error details, if any
+/// @return Map defining the window configuration, see |nvim_open_win()|
+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;
+ }
+
+ FloatConfig *config = &wp->w_float_config;
+
+ PUT(rv, "focusable", BOOLEAN_OBJ(config->focusable));
+ PUT(rv, "external", BOOLEAN_OBJ(config->external));
+
+ if (wp->w_floating) {
+ PUT(rv, "width", INTEGER_OBJ(config->width));
+ PUT(rv, "height", INTEGER_OBJ(config->height));
+ if (!config->external) {
+ if (config->relative == kFloatRelativeWindow) {
+ PUT(rv, "win", INTEGER_OBJ(config->window));
+ if (config->bufpos.lnum >= 0) {
+ Array pos = ARRAY_DICT_INIT;
+ ADD(pos, INTEGER_OBJ(config->bufpos.lnum));
+ ADD(pos, INTEGER_OBJ(config->bufpos.col));
+ PUT(rv, "bufpos", ARRAY_OBJ(pos));
+ }
+ }
+ PUT(rv, "anchor", STRING_OBJ(cstr_to_string(float_anchor_str[config->anchor])));
+ PUT(rv, "row", FLOAT_OBJ(config->row));
+ PUT(rv, "col", FLOAT_OBJ(config->col));
+ PUT(rv, "zindex", INTEGER_OBJ(config->zindex));
+ }
+ if (config->border) {
+ Array border = ARRAY_DICT_INIT;
+ for (size_t i = 0; i < 8; i++) {
+ Array tuple = ARRAY_DICT_INIT;
+
+ String s = cstrn_to_string((const char *)config->border_chars[i], sizeof(schar_T));
+
+ int hi_id = config->border_hl_ids[i];
+ char_u *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)));
+ ADD(border, ARRAY_OBJ(tuple));
+ } else {
+ ADD(border, STRING_OBJ(s));
+ }
+ }
+ PUT(rv, "border", ARRAY_OBJ(border));
+ }
+ }
+
+ const char *rel = (wp->w_floating && !config->external
+ ? float_relative_str[config->relative] : "");
+ PUT(rv, "relative", STRING_OBJ(cstr_to_string(rel)));
+
+ return rv;
+}
+
+static bool parse_float_anchor(String anchor, FloatAnchor *out)
+{
+ if (anchor.size == 0) {
+ *out = (FloatAnchor)0;
+ }
+ char *str = anchor.data;
+ if (striequal(str, "NW")) {
+ *out = 0; // NW is the default
+ } else if (striequal(str, "NE")) {
+ *out = kFloatAnchorEast;
+ } else if (striequal(str, "SW")) {
+ *out = kFloatAnchorSouth;
+ } else if (striequal(str, "SE")) {
+ *out = kFloatAnchorSouth | kFloatAnchorEast;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+static bool parse_float_relative(String relative, FloatRelative *out)
+{
+ char *str = relative.data;
+ if (striequal(str, "editor")) {
+ *out = kFloatRelativeEditor;
+ } else if (striequal(str, "win")) {
+ *out = kFloatRelativeWindow;
+ } else if (striequal(str, "cursor")) {
+ *out = kFloatRelativeCursor;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+static bool parse_float_bufpos(Array bufpos, lpos_T *out)
+{
+ if (bufpos.size != 2
+ || bufpos.items[0].type != kObjectTypeInteger
+ || bufpos.items[1].type != kObjectTypeInteger) {
+ return false;
+ }
+ out->lnum = bufpos.items[0].data.integer;
+ out->col = (colnr_T)bufpos.items[1].data.integer;
+ return true;
+}
+
+static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
+{
+ struct {
+ const char *name;
+ schar_T chars[8];
+ bool shadow_color;
+ } defaults[] = {
+ { "double", { "╔", "═", "╗", "║", "╝", "═", "╚", "║" }, false },
+ { "single", { "┌", "─", "┐", "│", "┘", "─", "└", "│" }, false },
+ { "shadow", { "", "", " ", " ", " ", " ", " ", "" }, true },
+ { "rounded", { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, false },
+ { "solid", { " ", " ", " ", " ", " ", " ", " ", " " }, false },
+ { NULL, { { NUL } }, false },
+ };
+
+ schar_T *chars = fconfig->border_chars;
+ int *hl_ids = fconfig->border_hl_ids;
+
+ fconfig->border = true;
+
+ if (style.type == kObjectTypeArray) {
+ Array arr = style.data.array;
+ size_t size = arr.size;
+ if (!size || size > 8 || (size & (size-1))) {
+ api_set_error(err, kErrorTypeValidation,
+ "invalid number of border chars");
+ return;
+ }
+ for (size_t i = 0; i < size; i++) {
+ Object iytem = arr.items[i];
+ String string;
+ int hl_id = 0;
+ if (iytem.type == kObjectTypeArray) {
+ Array iarr = iytem.data.array;
+ if (!iarr.size || iarr.size > 2) {
+ api_set_error(err, kErrorTypeValidation, "invalid border char");
+ return;
+ }
+ if (iarr.items[0].type != kObjectTypeString) {
+ api_set_error(err, kErrorTypeValidation, "invalid border char");
+ return;
+ }
+ string = iarr.items[0].data.string;
+ if (iarr.size == 2) {
+ hl_id = object_to_hl_id(iarr.items[1], "border char highlight", err);
+ if (ERROR_SET(err)) {
+ return;
+ }
+ }
+ } else if (iytem.type == kObjectTypeString) {
+ string = iytem.data.string;
+ } else {
+ api_set_error(err, kErrorTypeValidation, "invalid border char");
+ return;
+ }
+ if (string.size
+ && mb_string2cells_len((char_u *)string.data, string.size) > 1) {
+ api_set_error(err, kErrorTypeValidation,
+ "border chars must be one cell");
+ return;
+ }
+ size_t len = MIN(string.size, sizeof(*chars)-1);
+ if (len) {
+ memcpy(chars[i], string.data, len);
+ }
+ chars[i][len] = NUL;
+ hl_ids[i] = hl_id;
+ }
+ while (size < 8) {
+ memcpy(chars+size, chars, sizeof(*chars) * size);
+ memcpy(hl_ids+size, hl_ids, sizeof(*hl_ids) * size);
+ size <<= 1;
+ }
+ if ((chars[7][0] && chars[1][0] && !chars[0][0])
+ || (chars[1][0] && chars[3][0] && !chars[2][0])
+ || (chars[3][0] && chars[5][0] && !chars[4][0])
+ || (chars[5][0] && chars[7][0] && !chars[6][0])) {
+ api_set_error(err, kErrorTypeValidation,
+ "corner between used edges must be specified");
+ }
+ } else if (style.type == kObjectTypeString) {
+ String str = style.data.string;
+ if (str.size == 0 || strequal(str.data, "none")) {
+ fconfig->border = false;
+ return;
+ }
+ for (size_t i = 0; defaults[i].name; i++) {
+ if (strequal(str.data, defaults[i].name)) {
+ memcpy(chars, defaults[i].chars, sizeof(defaults[i].chars));
+ memset(hl_ids, 0, 8 * sizeof(*hl_ids));
+ if (defaults[i].shadow_color) {
+ int hl_blend = SYN_GROUP_STATIC("FloatShadow");
+ int hl_through = SYN_GROUP_STATIC("FloatShadowThrough");
+ hl_ids[2] = hl_through;
+ hl_ids[3] = hl_blend;
+ hl_ids[4] = hl_blend;
+ hl_ids[5] = hl_blend;
+ hl_ids[6] = hl_through;
+ }
+ return;
+ }
+ }
+ api_set_error(err, kErrorTypeValidation,
+ "invalid border style \"%s\"", str.data);
+ }
+}
+
+static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig, bool reconf,
+ bool new_win, Error *err)
+{
+ bool has_relative = false, relative_is_win = false;
+ if (config->relative.type == kObjectTypeString) {
+ // ignore empty string, to match nvim_win_get_config
+ if (config->relative.data.string.size > 0) {
+ if (!parse_float_relative(config->relative.data.string, &fconfig->relative)) {
+ api_set_error(err, kErrorTypeValidation, "Invalid value of 'relative' key");
+ return false;
+ }
+
+ if (!(HAS_KEY(config->row) && HAS_KEY(config->col)) && !HAS_KEY(config->bufpos)) {
+ api_set_error(err, kErrorTypeValidation,
+ "'relative' requires 'row'/'col' or 'bufpos'");
+ return false;
+ }
+
+ has_relative = true;
+ fconfig->external = false;
+ if (fconfig->relative == kFloatRelativeWindow) {
+ relative_is_win = true;
+ fconfig->bufpos.lnum = -1;
+ }
+ }
+ } else if (HAS_KEY(config->relative)) {
+ api_set_error(err, kErrorTypeValidation, "'relative' key must be String");
+ return false;
+ }
+
+ if (config->anchor.type == kObjectTypeString) {
+ if (!parse_float_anchor(config->anchor.data.string, &fconfig->anchor)) {
+ api_set_error(err, kErrorTypeValidation, "Invalid value of 'anchor' key");
+ return false;
+ }
+ } else if (HAS_KEY(config->anchor)) {
+ api_set_error(err, kErrorTypeValidation, "'anchor' key must be String");
+ return false;
+ }
+
+ if (HAS_KEY(config->row)) {
+ if (!has_relative) {
+ api_set_error(err, kErrorTypeValidation, "non-float cannot have 'row'");
+ return false;
+ } else if (config->row.type == kObjectTypeInteger) {
+ fconfig->row = (double)config->row.data.integer;
+ } else if (config->row.type == kObjectTypeFloat) {
+ fconfig->row = config->row.data.floating;
+ } else {
+ api_set_error(err, kErrorTypeValidation,
+ "'row' key must be Integer or Float");
+ return false;
+ }
+ }
+
+ if (HAS_KEY(config->col)) {
+ if (!has_relative) {
+ api_set_error(err, kErrorTypeValidation, "non-float cannot have 'col'");
+ return false;
+ } else if (config->col.type == kObjectTypeInteger) {
+ fconfig->col = (double)config->col.data.integer;
+ } else if (config->col.type == kObjectTypeFloat) {
+ fconfig->col = config->col.data.floating;
+ } else {
+ api_set_error(err, kErrorTypeValidation,
+ "'col' key must be Integer or Float");
+ return false;
+ }
+ }
+
+ if (HAS_KEY(config->bufpos)) {
+ if (!has_relative) {
+ api_set_error(err, kErrorTypeValidation, "non-float cannot have 'bufpos'");
+ return false;
+ } else if (config->bufpos.type == kObjectTypeArray) {
+ if (!parse_float_bufpos(config->bufpos.data.array, &fconfig->bufpos)) {
+ api_set_error(err, kErrorTypeValidation, "Invalid value of 'bufpos' key");
+ return false;
+ }
+
+ if (!HAS_KEY(config->row)) {
+ fconfig->row = (fconfig->anchor & kFloatAnchorSouth) ? 0 : 1;
+ }
+ if (!HAS_KEY(config->col)) {
+ fconfig->col = 0;
+ }
+ } else {
+ api_set_error(err, kErrorTypeValidation, "'bufpos' key must be Array");
+ return false;
+ }
+ }
+
+ if (config->width.type == kObjectTypeInteger && config->width.data.integer > 0) {
+ fconfig->width = (int)config->width.data.integer;
+ } else if (HAS_KEY(config->width)) {
+ api_set_error(err, kErrorTypeValidation, "'width' key must be a positive Integer");
+ return false;
+ } else if (!reconf) {
+ api_set_error(err, kErrorTypeValidation, "Must specify 'width'");
+ return false;
+ }
+
+ if (config->height.type == kObjectTypeInteger && config->height.data.integer > 0) {
+ fconfig->height = (int)config->height.data.integer;
+ } else if (HAS_KEY(config->height)) {
+ api_set_error(err, kErrorTypeValidation, "'height' key must be a positive Integer");
+ return false;
+ } else if (!reconf) {
+ api_set_error(err, kErrorTypeValidation, "Must specify 'height'");
+ return false;
+ }
+
+ if (relative_is_win) {
+ fconfig->window = curwin->handle;
+ if (config->win.type == kObjectTypeInteger || config->win.type == kObjectTypeWindow) {
+ if (config->win.data.integer > 0) {
+ fconfig->window = (Window)config->win.data.integer;
+ }
+ } else if (HAS_KEY(config->win)) {
+ api_set_error(err, kErrorTypeValidation, "'win' key must be Integer or Window");
+ return false;
+ }
+ } else {
+ if (HAS_KEY(config->win)) {
+ api_set_error(err, kErrorTypeValidation, "'win' key is only valid with relative='win'");
+ return false;
+ }
+ }
+
+ if (HAS_KEY(config->external)) {
+ fconfig->external = api_object_to_bool(config->external, "'external' key", false, err);
+ if (ERROR_SET(err)) {
+ return false;
+ }
+ if (has_relative && fconfig->external) {
+ api_set_error(err, kErrorTypeValidation,
+ "Only one of 'relative' and 'external' must be used");
+ return false;
+ }
+ if (fconfig->external && !ui_has(kUIMultigrid)) {
+ api_set_error(err, kErrorTypeValidation,
+ "UI doesn't support external windows");
+ return false;
+ }
+ }
+
+ if (!reconf && (!has_relative && !fconfig->external)) {
+ api_set_error(err, kErrorTypeValidation,
+ "One of 'relative' and 'external' must be used");
+ return false;
+ }
+
+
+ if (HAS_KEY(config->focusable)) {
+ fconfig->focusable = api_object_to_bool(config->focusable, "'focusable' key", false, err);
+ if (ERROR_SET(err)) {
+ return false;
+ }
+ }
+
+ if (config->zindex.type == kObjectTypeInteger && config->zindex.data.integer > 0) {
+ fconfig->zindex = (int)config->zindex.data.integer;
+ } else if (HAS_KEY(config->zindex)) {
+ api_set_error(err, kErrorTypeValidation, "'zindex' key must be a positive Integer");
+ return false;
+ }
+
+ if (HAS_KEY(config->border)) {
+ parse_border_style(config->border, fconfig, err);
+ if (ERROR_SET(err)) {
+ return false;
+ }
+ }
+
+ if (config->style.type == kObjectTypeString) {
+ if (config->style.data.string.data[0] == NUL) {
+ fconfig->style = kWinStyleUnused;
+ } else if (striequal(config->style.data.string.data, "minimal")) {
+ fconfig->style = kWinStyleMinimal;
+ } else {
+ api_set_error(err, kErrorTypeValidation, "Invalid value of 'style' key");
+ }
+ } else if (HAS_KEY(config->style)) {
+ api_set_error(err, kErrorTypeValidation, "'style' key must be String");
+ return false;
+ }
+
+ if (HAS_KEY(config->noautocmd)) {
+ if (!new_win) {
+ api_set_error(err, kErrorTypeValidation, "Invalid key: 'noautocmd'");
+ return false;
+ }
+ fconfig->noautocmd = api_object_to_bool(config->noautocmd, "'noautocmd' key", false, err);
+ if (ERROR_SET(err)) {
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/src/nvim/api/win_config.h b/src/nvim/api/win_config.h
new file mode 100644
index 0000000000..9271c35f23
--- /dev/null
+++ b/src/nvim/api/win_config.h
@@ -0,0 +1,11 @@
+#ifndef NVIM_API_WIN_CONFIG_H
+#define NVIM_API_WIN_CONFIG_H
+
+#include <stdint.h>
+
+#include "nvim/api/private/defs.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "api/win_config.h.generated.h"
+#endif
+#endif // NVIM_API_WIN_CONFIG_H
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index 95eae1af2d..6e68c057dc 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -373,117 +373,6 @@ Boolean nvim_win_is_valid(Window window)
}
-/// Configures window layout. Currently only for floating and external windows
-/// (including changing a split window to those layouts).
-///
-/// When reconfiguring a floating window, absent option keys will not be
-/// changed. `row`/`col` and `relative` must be reconfigured together.
-///
-/// @see |nvim_open_win()|
-///
-/// @param window Window handle, or 0 for current window
-/// @param config Map defining the window configuration,
-/// see |nvim_open_win()|
-/// @param[out] err Error details, if any
-void nvim_win_set_config(Window window, Dict(float_config) *config, Error *err)
- FUNC_API_SINCE(6)
-{
- win_T *win = find_window_by_handle(window, err);
- if (!win) {
- return;
- }
- bool new_float = !win->w_floating;
- // reuse old values, if not overridden
- FloatConfig fconfig = new_float ? FLOAT_CONFIG_INIT : win->w_float_config;
-
- if (!parse_float_config(config, &fconfig, !new_float, false, err)) {
- return;
- }
- if (new_float) {
- if (!win_new_float(win, fconfig, err)) {
- return;
- }
- redraw_later(win, NOT_VALID);
- } else {
- win_config_float(win, fconfig);
- win->w_pos_changed = true;
- }
- if (fconfig.style == kWinStyleMinimal) {
- win_set_minimal_style(win);
- didset_window_options(win);
- }
-}
-
-/// Gets window configuration.
-///
-/// The returned value may be given to |nvim_open_win()|.
-///
-/// `relative` is empty for normal windows.
-///
-/// @param window Window handle, or 0 for current window
-/// @param[out] err Error details, if any
-/// @return Map defining the window configuration, see |nvim_open_win()|
-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;
- }
-
- FloatConfig *config = &wp->w_float_config;
-
- PUT(rv, "focusable", BOOLEAN_OBJ(config->focusable));
- PUT(rv, "external", BOOLEAN_OBJ(config->external));
-
- if (wp->w_floating) {
- PUT(rv, "width", INTEGER_OBJ(config->width));
- PUT(rv, "height", INTEGER_OBJ(config->height));
- if (!config->external) {
- if (config->relative == kFloatRelativeWindow) {
- PUT(rv, "win", INTEGER_OBJ(config->window));
- if (config->bufpos.lnum >= 0) {
- Array pos = ARRAY_DICT_INIT;
- ADD(pos, INTEGER_OBJ(config->bufpos.lnum));
- ADD(pos, INTEGER_OBJ(config->bufpos.col));
- PUT(rv, "bufpos", ARRAY_OBJ(pos));
- }
- }
- PUT(rv, "anchor", STRING_OBJ(cstr_to_string(float_anchor_str[config->anchor])));
- PUT(rv, "row", FLOAT_OBJ(config->row));
- PUT(rv, "col", FLOAT_OBJ(config->col));
- PUT(rv, "zindex", INTEGER_OBJ(config->zindex));
- }
- if (config->border) {
- Array border = ARRAY_DICT_INIT;
- for (size_t i = 0; i < 8; i++) {
- Array tuple = ARRAY_DICT_INIT;
-
- String s = cstrn_to_string((const char *)config->border_chars[i], sizeof(schar_T));
-
- int hi_id = config->border_hl_ids[i];
- char_u *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)));
- ADD(border, ARRAY_OBJ(tuple));
- } else {
- ADD(border, STRING_OBJ(s));
- }
- }
- PUT(rv, "border", ARRAY_OBJ(border));
- }
- }
-
- const char *rel = (wp->w_floating && !config->external
- ? float_relative_str[config->relative] : "");
- PUT(rv, "relative", STRING_OBJ(cstr_to_string(rel)));
-
- return rv;
-}
-
/// Closes the window and hide the buffer it contains (like |:hide| with a
/// |window-ID|).
///
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index f899ebf57c..d2f95ad81c 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -412,7 +412,7 @@ char *transstr(const char *const s, bool untab)
{
// Compute the length of the result, taking account of unprintable
// multi-byte characters.
- const size_t len = transstr_len((const char *)s, untab) + 1;
+ const size_t len = transstr_len(s, untab) + 1;
char *const buf = xmalloc(len);
transstr_buf(s, buf, len, untab);
return buf;
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 5c43b2498e..3a7bd21c70 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -1110,7 +1110,7 @@ static int diff_file(diffio_T *dio)
// Build the diff command and execute it. Always use -a, binary
// differences are of no use. Ignore errors, diff returns
// non-zero when differences have been found.
- vim_snprintf((char *)cmd, len, "diff %s%s%s%s%s%s%s%s %s",
+ vim_snprintf(cmd, len, "diff %s%s%s%s%s%s%s%s %s",
diff_a_works == kFalse ? "" : "-a ",
"",
(diff_flags & DIFF_IWHITE) ? "-b " : "",
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 45edbec4a6..5ac733285d 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -116,7 +116,7 @@ static char *ctrl_x_msgs[] =
static char *ctrl_x_mode_names[] = {
"keyword",
"ctrl_x",
- "unknown", // CTRL_X_SCROLL
+ "scroll",
"whole_line",
"files",
"tags",
@@ -3329,7 +3329,7 @@ void get_complete_info(list_T *what_list, dict_T *retdict)
// Return Insert completion mode name string
static char_u *ins_compl_mode(void)
{
- if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET || compl_started) {
+ if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET || ctrl_x_mode == CTRL_X_SCROLL || compl_started) {
return (char_u *)ctrl_x_mode_names[ctrl_x_mode & ~CTRL_X_WANT_IDENT];
}
return (char_u *)"";
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 768b82b464..a281c09042 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -514,8 +514,8 @@ int var_redir_start(char_u *name, int append)
ga_init(&redir_ga, (int)sizeof(char), 500);
// Parse the variable name (can be a dict or list entry).
- redir_endp = (char_u *)get_lval(redir_varname, NULL, redir_lval, false, false,
- 0, FNE_CHECK_START);
+ redir_endp = get_lval(redir_varname, NULL, redir_lval, false, false,
+ 0, FNE_CHECK_START);
if (redir_endp == NULL || redir_lval->ll_name == NULL
|| *redir_endp != NUL) {
clear_lval(redir_lval);
@@ -597,8 +597,8 @@ void var_redir_stop(void)
tv.vval.v_string = redir_ga.ga_data;
// Call get_lval() again, if it's inside a Dict or List it may
// have changed.
- redir_endp = (char_u *)get_lval(redir_varname, NULL, redir_lval,
- false, false, 0, FNE_CHECK_START);
+ redir_endp = get_lval(redir_varname, NULL, redir_lval,
+ false, false, 0, FNE_CHECK_START);
if (redir_endp != NULL && redir_lval->ll_name != NULL) {
set_var_lval(redir_lval, redir_endp, &tv, false, false, ".");
}
@@ -1711,7 +1711,7 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first)
if (tofree != NULL) {
name = tofree;
}
- if (get_var_tv((const char *)name, len, &tv, NULL, true, false)
+ if (get_var_tv(name, len, &tv, NULL, true, false)
== FAIL) {
error = true;
} else {
@@ -2023,7 +2023,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co
}
lp->ll_exp_name = (char *)make_expanded_name(name, expr_start, expr_end,
- (char_u *)p);
+ p);
lp->ll_name = lp->ll_exp_name;
if (lp->ll_exp_name == NULL) {
/* Report an invalid expression in braces, unless the
@@ -2419,7 +2419,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, co
// handle +=, -=, *=, /=, %= and .=
di = NULL;
- if (get_var_tv((const char *)lp->ll_name, (int)STRLEN(lp->ll_name),
+ if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
&tv, &di, true, false) == OK) {
if ((di == NULL
|| (!var_check_ro(di->di_flags, lp->ll_name, TV_CSTRING)
@@ -3004,12 +3004,12 @@ int do_unlet(const char *const name, const size_t name_len, const bool forceit)
hashitem_T *hi = hash_find(ht, (const char_u *)varname);
if (HASHITEM_EMPTY(hi)) {
- hi = find_hi_in_scoped_ht((const char *)name, &ht);
+ hi = find_hi_in_scoped_ht(name, &ht);
}
if (hi != NULL && !HASHITEM_EMPTY(hi)) {
dictitem_T *const di = TV_DICT_HI2DI(hi);
- if (var_check_fixed(di->di_flags, (const char *)name, TV_CSTRING)
- || var_check_ro(di->di_flags, (const char *)name, TV_CSTRING)
+ if (var_check_fixed(di->di_flags, name, TV_CSTRING)
+ || var_check_ro(di->di_flags, name, TV_CSTRING)
|| var_check_lock(d->dv_lock, name, TV_CSTRING)) {
return FAIL;
}
@@ -3069,7 +3069,7 @@ static int do_lock_var(lval_T *lp, char_u *name_end FUNC_ATTR_UNUSED, exarg_T *e
ret = FAIL;
} else {
// Normal name or expanded name.
- dictitem_T *const di = find_var((const char *)lp->ll_name, lp->ll_name_len, NULL,
+ dictitem_T *const di = find_var(lp->ll_name, lp->ll_name_len, NULL,
true);
if (di == NULL) {
ret = FAIL;
@@ -4348,7 +4348,7 @@ static int call_func_rettv(char_u **const arg, typval_T *const rettv, const bool
funcexe.selfdict = selfdict;
funcexe.basetv = basetv;
const int ret = get_func_tv(funcname, is_lua ? *arg - funcname : -1, rettv,
- (char_u **)arg, &funcexe);
+ arg, &funcexe);
// Clear the funcref afterwards, so that deleting it while
// evaluating the arguments is possible (see test55).
@@ -9444,7 +9444,7 @@ static void set_var_const(const char *name, const size_t name_len, typval_T *con
// Search in parent scope which is possible to reference from lambda
if (v == NULL) {
- v = find_var_in_scoped_ht((const char *)name, name_len, true);
+ v = find_var_in_scoped_ht(name, name_len, true);
}
if (tv_is_func(*tv) && !var_check_func_name(name, v == NULL)) {
@@ -9654,7 +9654,7 @@ bool var_check_func_name(const char *const name, const bool new_var)
// Don't allow hiding a function. When "v" is not NULL we might be
// assigning another function to the same var, the type is checked
// below.
- if (new_var && function_exists((const char *)name, false)) {
+ if (new_var && function_exists(name, false)) {
EMSG2(_("E705: Variable name conflicts with existing function: %s"),
name);
return false;
@@ -11325,7 +11325,7 @@ bool var_exists(const char *var)
// get_name_len() takes care of expanding curly braces
const char *name = var;
- const int len = get_name_len((const char **)&var, &tofree, true, false);
+ const int len = get_name_len(&var, &tofree, true, false);
if (len > 0) {
typval_T tv;
diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c
index 1c0afc89f5..5ef0045659 100644
--- a/src/nvim/eval/encode.c
+++ b/src/nvim/eval/encode.c
@@ -268,9 +268,8 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
|| TV_LIST_ITEM_TV(state->li)->vval.v_string != NULL);
for (size_t i = state->offset; i < state->li_length && p < buf_end; i++) {
assert(TV_LIST_ITEM_TV(state->li)->vval.v_string != NULL);
- const char ch = (char)(
- TV_LIST_ITEM_TV(state->li)->vval.v_string[state->offset++]);
- *p++ = (char)((char)ch == (char)NL ? (char)NUL : (char)ch);
+ const char ch = (char)(TV_LIST_ITEM_TV(state->li)->vval.v_string[state->offset++]);
+ *p++ = (char)(ch == (char)NL ? (char)NUL : ch);
}
if (p < buf_end) {
state->li = TV_LIST_ITEM_NEXT(state->list, state->li);
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 5569d74413..50e0b0b258 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -5149,7 +5149,7 @@ static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr)
EMSG(_(e_trailing));
} else {
if (lv.ll_tv == NULL) {
- di = find_var((const char *)lv.ll_name, lv.ll_name_len, NULL, true);
+ di = find_var(lv.ll_name, lv.ll_name_len, NULL, true);
if (di != NULL) {
// Consider a variable locked when:
// 1. the variable itself is locked
@@ -5984,7 +5984,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
static void f_luaeval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
FUNC_ATTR_NONNULL_ALL
{
- const char *const str = (const char *)tv_get_string_chk(&argvars[0]);
+ const char *const str = tv_get_string_chk(&argvars[0]);
if (str == NULL) {
return;
}
@@ -11358,7 +11358,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (new_cwd && *new_cwd != NUL) {
cwd = new_cwd;
// The new cwd must be a directory.
- if (!os_isdir_executable((const char *)cwd)) {
+ if (!os_isdir_executable(cwd)) {
EMSG2(_(e_invarg2), "expected valid directory");
shell_free_argv(argv);
return;
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index 075b50a366..4c8789964f 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -3260,7 +3260,7 @@ const char *tv_get_string(const typval_T *const tv)
const char *tv_get_string_buf(const typval_T *const tv, char *const buf)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
{
- const char *const res = (const char *)tv_get_string_buf_chk(tv, buf);
+ const char *const res = tv_get_string_buf_chk(tv, buf);
return res != NULL ? res : "";
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index a9990df58f..e0ff9bab3a 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -3037,7 +3037,7 @@ static void ui_ext_cmdline_show(CmdlineInfo *line)
line->cmdindent,
line->level);
if (line->special_char) {
- ui_call_cmdline_special_char(cchar_to_string((char)(line->special_char)),
+ ui_call_cmdline_special_char(cchar_to_string(line->special_char),
line->special_shift,
line->level);
}
@@ -3135,7 +3135,7 @@ void putcmdline(char c, int shift)
}
msg_no_more = false;
} else if (ccline.redraw_state != kCmdRedrawAll) {
- ui_call_cmdline_special_char(cchar_to_string((char)(c)), shift,
+ ui_call_cmdline_special_char(cchar_to_string(c), shift,
ccline.level);
}
cursorcmd();
diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua
index 6ed2e5dab8..e38a0af0ec 100644
--- a/src/nvim/generators/gen_api_dispatch.lua
+++ b/src/nvim/generators/gen_api_dispatch.lua
@@ -33,6 +33,10 @@ local function_names = {}
local c_grammar = require('generators.c_grammar')
+local function startswith(String,Start)
+ return string.sub(String,1,string.len(Start))==Start
+end
+
-- read each input file, parse and append to the api metadata
for i = 6, #arg do
local full_path = arg[i]
@@ -47,7 +51,8 @@ for i = 6, #arg do
local tmp = c_grammar.grammar:match(input:read('*all'))
for j = 1, #tmp do
local fn = tmp[j]
- if not fn.noexport then
+ local public = startswith(fn.name, "nvim_") or fn.deprecated_since
+ if public and not fn.noexport then
functions[#functions + 1] = tmp[j]
function_names[fn.name] = true
if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then
@@ -76,10 +81,6 @@ local function shallowcopy(orig)
return copy
end
-local function startswith(String,Start)
- return string.sub(String,1,string.len(Start))==Start
-end
-
-- Export functions under older deprecated names.
-- These will be removed eventually.
local deprecated_aliases = require("api.dispatch_deprecated")
@@ -108,9 +109,10 @@ for _,f in ipairs(shallowcopy(functions)) do
f.lua = f.lua_only or not f.remote_only
f.eval = (not f.lua_only) and (not f.remote_only)
else
+ f.deprecated_since = tonumber(f.deprecated_since)
+ assert(f.deprecated_since == 1)
f.remote = true
f.since = 0
- f.deprecated_since = 1
end
f.method = ismethod
local newname = deprecated_aliases[f.name]
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 15acd73aa5..f5f8a307d1 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -523,7 +523,7 @@ void restoreRedobuff(save_redo_T *save_redo)
void AppendToRedobuff(const char *s)
{
if (!block_redo) {
- add_buff(&redobuff, (const char *)s, -1L);
+ add_buff(&redobuff, s, -1L);
}
}
@@ -2861,7 +2861,7 @@ int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev, buf_T
}
char_u *lhs = (char_u *)&args->lhs;
- char_u *rhs = (char_u *)args->rhs;
+ char_u *rhs = args->rhs;
char_u *orig_rhs = args->orig_rhs;
// check arguments and translate function keys
diff --git a/src/nvim/main.c b/src/nvim/main.c
index f801351d2d..069c253bff 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -345,7 +345,8 @@ int main(int argc, char **argv)
// Reset 'loadplugins' for "-u NONE" before "--cmd" arguments.
// Allows for setting 'loadplugins' there.
if (params.use_vimrc != NULL && strequal(params.use_vimrc, "NONE")) {
- p_lpl = false;
+ // When using --clean we still want to load plugins
+ p_lpl = params.clean;
}
// Execute --cmd arguments.
diff --git a/src/nvim/message.c b/src/nvim/message.c
index ed673b52d3..edde51e770 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -3191,7 +3191,7 @@ static void redir_write(const char *const str, const ptrdiff_t maxlen)
size_t len = maxlen == -1 ? STRLEN(s) : (size_t)maxlen;
if (capture_ga) {
- ga_concat_len(capture_ga, (const char *)str, len);
+ ga_concat_len(capture_ga, str, len);
}
if (redir_reg) {
write_reg_contents(redir_reg, s, len, true);
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index bbf70a4830..9675cfbb0f 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -134,7 +134,7 @@ bool os_isdir(const char_u *name)
bool os_isdir_executable(const char *name)
FUNC_ATTR_NONNULL_ALL
{
- int32_t mode = os_getperm((const char *)name);
+ int32_t mode = os_getperm(name);
if (mode < 0) {
return false;
}
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index eb0ba874f4..046e6dbd12 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -1823,7 +1823,7 @@ static int qf_add_entry(qf_list_T *qfl, char_u *dir, char_u *fname, char_u *modu
if (type != 1 && !vim_isprintc(type)) { // only printable chars allowed
type = 0;
}
- qfp->qf_type = (char_u)type;
+ qfp->qf_type = type;
qfp->qf_valid = valid;
lastp = &qfl->qf_last;
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index e1669a8c19..0e2d23e69b 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -335,7 +335,7 @@ int do_in_path_and_pp(char_u *path, char_u *name, int flags, DoInRuntimepathCB c
static void push_path(RuntimeSearchPath *search_path, Map(String, handle_T) *rtp_used,
char *entry, bool after)
{
- handle_T h = map_get(String, handle_T)(rtp_used, cstr_as_string((char *)entry));
+ handle_T h = map_get(String, handle_T)(rtp_used, cstr_as_string(entry));
if (h == 0) {
char *allocated = xstrdup(entry);
map_put(String, handle_T)(rtp_used, cstr_as_string(allocated), 1);
@@ -776,7 +776,7 @@ static bool pack_has_entries(char_u *buf)
{
int num_files;
char_u **files;
- char_u *(pat[]) = { (char_u *)buf };
+ char_u *(pat[]) = { buf };
if (gen_expand_wildcards(1, pat, &num_files, &files, EW_DIR) == OK) {
FreeWild(num_files, files);
}
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index bf245bec51..2d65db8437 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -65,25 +65,10 @@ KHASH_SET_INIT_INT64(bufset)
KHASH_MAP_INIT_STR(fnamebufs, buf_T *)
KHASH_SET_INIT_STR(strset)
-#define copy_option_part(src, dest, ...) \
- ((char *)copy_option_part((char_u **)src, (char_u *)dest, __VA_ARGS__))
#define find_shada_parameter(...) \
((const char *)find_shada_parameter(__VA_ARGS__))
-#define home_replace_save(a, b) \
- ((char *)home_replace_save(a, (char_u *)b))
-#define home_replace(a, b, c, d, e) \
- home_replace(a, (char_u *)b, (char_u *)c, d, e)
-#define vim_rename(a, b) \
- (vim_rename((char_u *)a, (char_u *)b))
-#define mb_strnicmp(a, b, c) \
- (mb_strnicmp((char_u *)a, (char_u *)b, c))
#define path_try_shorten_fname(b) \
((char *)path_try_shorten_fname((char_u *)b))
-#define buflist_new(ffname, sfname, ...) \
- (buflist_new((char_u *)ffname, (char_u *)sfname, __VA_ARGS__))
-#define os_isdir(f) (os_isdir((char_u *)f))
-#define regtilde(s, m) ((char *)regtilde((char_u *)s, m))
-#define path_tail_with_sep(f) ((char *)path_tail_with_sep((char_u *)f))
#define SEARCH_KEY_MAGIC "sm"
#define SEARCH_KEY_SMARTCASE "sc"
@@ -1271,7 +1256,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
// string is close to useless: you can only use it with :& or :~ and
// that’s all because s//~ is not available until the first call to
// regtilde. Vim was not calling this for some reason.
- (void)regtilde(cur_entry.data.sub_string.sub, p_magic);
+ (void)(char *)regtilde((char_u *)cur_entry.data.sub_string.sub, p_magic);
// Do not free shada entry: its allocated memory was saved above.
break;
case kSDItemHistoryEntry:
@@ -1362,8 +1347,9 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
case kSDItemBufferList:
for (size_t i = 0; i < cur_entry.data.buffer_list.size; i++) {
char *const sfname = path_try_shorten_fname(cur_entry.data.buffer_list.buffers[i].fname);
- buf_T *const buf = buflist_new(cur_entry.data.buffer_list.buffers[i].fname, sfname, 0,
- BLN_LISTED);
+ buf_T *const buf =
+ buflist_new((char_u *)cur_entry.data.buffer_list.buffers[i].fname, (char_u *)sfname, 0,
+ BLN_LISTED);
if (buf != NULL) {
RESET_FMARK(&buf->b_last_cursor,
cur_entry.data.buffer_list.buffers[i].pos, 0);
@@ -2694,7 +2680,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef
.timestamp = sub.timestamp,
.data = {
.sub_string = {
- .sub = (char *)sub.sub,
+ .sub = sub.sub,
.additional_elements = sub.additional_elements,
}
}
@@ -3037,11 +3023,11 @@ shada_write_file_open: {}
}
if (nomerge) {
shada_write_file_nomerge: {}
- char *const tail = path_tail_with_sep(fname);
+ char *const tail = (char *)path_tail_with_sep((char_u *)fname);
if (tail != fname) {
const char tail_save = *tail;
*tail = NUL;
- if (!os_isdir(fname)) {
+ if (!os_isdir((char_u *)fname)) {
int ret;
char *failed_dir;
if ((ret = os_mkdir_recurse(fname, 0700, &failed_dir)) != 0) {
@@ -3092,7 +3078,7 @@ shada_write_file_nomerge: {}
// overwrite a user’s viminfo file after a "su root", with a
// viminfo file that the user can't read.
FileInfo old_info;
- if (os_fileinfo((char *)fname, &old_info)) {
+ if (os_fileinfo(fname, &old_info)) {
if (getuid() == ROOT_UID) {
if (old_info.stat.st_uid != ROOT_UID
|| old_info.stat.st_gid != getgid()) {
@@ -3116,7 +3102,7 @@ shada_write_file_nomerge: {}
}
}
#endif
- if (vim_rename(tempname, fname) == -1) {
+ if (vim_rename((char_u *)tempname, (char_u *)fname) == -1) {
EMSG3(_(RNERR "Can't rename ShaDa file from %s to %s!"),
tempname, fname);
} else {
@@ -4015,13 +4001,13 @@ static bool shada_removable(const char *name)
char part[MAXPATHL + 1];
bool retval = false;
- char *new_name = home_replace_save(NULL, name);
+ char *new_name = (char *)home_replace_save(NULL, (char_u *)name);
for (p = (char *)p_shada; *p; ) {
- (void)copy_option_part(&p, part, ARRAY_SIZE(part), ", ");
+ (void)(char *)copy_option_part((char_u **)&p, (char_u *)part, ARRAY_SIZE(part), ", ");
if (part[0] == 'r') {
- home_replace(NULL, part + 1, NameBuff, MAXPATHL, true);
+ home_replace(NULL, (char_u *)(part + 1), (char_u *)NameBuff, MAXPATHL, true);
size_t n = STRLEN(NameBuff);
- if (mb_strnicmp(NameBuff, new_name, n) == 0) {
+ if (mb_strnicmp((char_u *)NameBuff, (char_u *)new_name, n) == 0) {
retval = true;
break;
}
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 3e56ad561b..450ec891ad 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -6073,7 +6073,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
wordlen = 0;
for (const char_u *s = inword; *s != NUL; ) {
const char_u *t = s;
- c = mb_cptr2char_adv((const char_u **)&s);
+ c = mb_cptr2char_adv(&s);
if (slang->sl_rem_accents) {
if (utf_class(c) == 0) {
if (did_white) {
diff --git a/src/nvim/state.c b/src/nvim/state.c
index a9f3d67849..04271d750c 100644
--- a/src/nvim/state.c
+++ b/src/nvim/state.c
@@ -161,6 +161,11 @@ char *get_mode(void)
if (State & VREPLACE_FLAG) {
buf[0] = 'R';
buf[1] = 'v';
+ if (ins_compl_active()) {
+ buf[2] = 'c';
+ } else if (ctrl_x_mode_not_defined_yet()) {
+ buf[2] = 'x';
+ }
} else {
if (State & REPLACE_FLAG) {
buf[0] = 'R';
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index d2c94d9fe8..49f54dcfe1 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -6217,6 +6217,26 @@ static const char *highlight_init_both[] = {
"default link Delimiter Special",
"default link SpecialComment Special",
"default link Debug Special",
+ "default DiagnosticError ctermfg=1 guifg=Red",
+ "default DiagnosticWarn ctermfg=3 guifg=Orange",
+ "default DiagnosticInfo ctermfg=4 guifg=LightBlue",
+ "default DiagnosticHint ctermfg=7 guifg=LightGrey",
+ "default DiagnosticUnderlineError cterm=underline gui=underline guisp=Red",
+ "default DiagnosticUnderlineWarn cterm=underline gui=underline guisp=Orange",
+ "default DiagnosticUnderlineInfo cterm=underline gui=underline guisp=LightBlue",
+ "default DiagnosticUnderlineHint cterm=underline gui=underline guisp=LightGrey",
+ "default link DiagnosticVirtualTextError DiagnosticError",
+ "default link DiagnosticVirtualTextWarn DiagnosticWarn",
+ "default link DiagnosticVirtualTextInfo DiagnosticInfo",
+ "default link DiagnosticVirtualTextHint DiagnosticHint",
+ "default link DiagnosticFloatingError DiagnosticError",
+ "default link DiagnosticFloatingWarn DiagnosticWarn",
+ "default link DiagnosticFloatingInfo DiagnosticInfo",
+ "default link DiagnosticFloatingHint DiagnosticHint",
+ "default link DiagnosticSignError DiagnosticError",
+ "default link DiagnosticSignWarn DiagnosticWarn",
+ "default link DiagnosticSignInfo DiagnosticInfo",
+ "default link DiagnosticSignHint DiagnosticHint",
NULL
};
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index 9eb64f68ef..4a9cb4a8d8 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -259,7 +259,7 @@ let s:filename_checks = {
\ 'jgraph': ['file.jgr'],
\ 'jovial': ['file.jov', 'file.j73', 'file.jovial'],
\ 'jproperties': ['file.properties', 'file.properties_xx', 'file.properties_xx_xx', 'some.properties_xx_xx_file'],
- \ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb'],
+ \ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', '.babelrc', '.eslintrc', '.prettierrc', '.firebaserc'],
\ 'jsonc': ['file.jsonc'],
\ 'jsp': ['file.jsp'],
\ 'julia': ['file.jl'],
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index e82fefc7fc..366615821c 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -585,6 +585,8 @@ func Test_mode()
exe "normal iabc\<C-X>\<C-L>\<F2>\<Esc>u"
call assert_equal('i-ic', g:current_modes)
+ exe "normal R\<F2>\<Esc>"
+ call assert_equal('R-R', g:current_modes)
" R_CTRL-P: Multiple matches
exe "normal RBa\<C-P>\<F2>\<Esc>u"
call assert_equal('R-Rc', g:current_modes)
@@ -619,6 +621,42 @@ func Test_mode()
exe "normal Rabc\<C-X>\<C-L>\<F2>\<Esc>u"
call assert_equal('R-Rc', g:current_modes)
+ exe "normal gR\<F2>\<Esc>"
+ call assert_equal('R-Rv', g:current_modes)
+ " gR_CTRL-P: Multiple matches
+ exe "normal gRBa\<C-P>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-P: Single match
+ exe "normal gRBro\<C-P>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-X
+ exe "normal gRBa\<C-X>\<F2>\<Esc>u"
+ call assert_equal('R-Rvx', g:current_modes)
+ " gR_CTRL-X CTRL-P: Multiple matches
+ exe "normal gRBa\<C-X>\<C-P>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-X CTRL-P: Single match
+ exe "normal gRBro\<C-X>\<C-P>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-X CTRL-P + CTRL-P: Single match
+ exe "normal gRBro\<C-X>\<C-P>\<C-P>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-X CTRL-L: Multiple matches
+ exe "normal gR\<C-X>\<C-L>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-X CTRL-L: Single match
+ exe "normal gRBlu\<C-X>\<C-L>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-P: No match
+ exe "normal gRCom\<C-P>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-X CTRL-P: No match
+ exe "normal gRCom\<C-X>\<C-P>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+ " gR_CTRL-X CTRL-L: No match
+ exe "normal gRabc\<C-X>\<C-L>\<F2>\<Esc>u"
+ call assert_equal('R-Rvc', g:current_modes)
+
call assert_equal('n', mode(0))
call assert_equal('n', mode(1))
diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim
index 710450293c..eb367cfe5c 100644
--- a/src/nvim/testdir/test_popup.vim
+++ b/src/nvim/testdir/test_popup.vim
@@ -950,6 +950,10 @@ func Test_popup_complete_info_01()
\ ["\<C-X>", 'ctrl_x'],
\ ["\<C-X>\<C-N>", 'keyword'],
\ ["\<C-X>\<C-P>", 'keyword'],
+ \ ["\<C-X>\<C-E>", 'scroll'],
+ \ ["\<C-X>\<C-Y>", 'scroll'],
+ \ ["\<C-X>\<C-E>\<C-E>\<C-Y>", 'scroll'],
+ \ ["\<C-X>\<C-Y>\<C-E>\<C-Y>", 'scroll'],
\ ["\<C-X>\<C-L>", 'whole_line'],
\ ["\<C-X>\<C-F>", 'files'],
\ ["\<C-X>\<C-]>", 'tags'],
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index af214815f8..d5857ff8b9 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -1407,7 +1407,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT
FileInfo file_info_orig;
FileInfo file_info_undo;
if (os_fileinfo((const char *)orig_name, &file_info_orig)
- && os_fileinfo((char *)file_name, &file_info_undo)
+ && os_fileinfo(file_name, &file_info_undo)
&& file_info_orig.stat.st_uid != file_info_undo.stat.st_uid
&& file_info_undo.stat.st_uid != getuid()) {
if (p_verbose > 0) {
@@ -1420,7 +1420,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT
}
#endif
} else {
- file_name = (char *)name;
+ file_name = name;
}
if (p_verbose > 0) {
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index a066cfbc10..8651a38025 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -237,29 +237,34 @@ describe('lua stdlib', function()
end)
it("vim.split", function()
- local split = function(str, sep, plain)
- return exec_lua('return vim.split(...)', str, sep, plain)
+ local split = function(str, sep, kwargs)
+ return exec_lua('return vim.split(...)', str, sep, kwargs)
end
local tests = {
- { "a,b", ",", false, { 'a', 'b' } },
- { ":aa::bb:", ":", false, { '', 'aa', '', 'bb', '' } },
- { "::ee::ff:", ":", false, { '', '', 'ee', '', 'ff', '' } },
- { "ab", ".", false, { '', '', '' } },
- { "a1b2c", "[0-9]", false, { 'a', 'b', 'c' } },
- { "xy", "", false, { 'x', 'y' } },
- { "here be dragons", " ", false, { "here", "be", "dragons"} },
- { "axaby", "ab?", false, { '', 'x', 'y' } },
- { "f v2v v3v w2w ", "([vw])2%1", false, { 'f ', ' v3v ', ' ' } },
- { "", "", false, {} },
- { "", "a", false, { '' } },
- { "x*yz*oo*l", "*", true, { 'x', 'yz', 'oo', 'l' } },
+ { "a,b", ",", false, false, { 'a', 'b' } },
+ { ":aa::bb:", ":", false, false, { '', 'aa', '', 'bb', '' } },
+ { ":aa::bb:", ":", false, true, { 'aa', '', 'bb' } },
+ { "::ee::ff:", ":", false, false, { '', '', 'ee', '', 'ff', '' } },
+ { "::ee::ff:", ":", false, true, { 'ee', '', 'ff' } },
+ { "ab", ".", false, false, { '', '', '' } },
+ { "a1b2c", "[0-9]", false, false, { 'a', 'b', 'c' } },
+ { "xy", "", false, false, { 'x', 'y' } },
+ { "here be dragons", " ", false, false, { "here", "be", "dragons"} },
+ { "axaby", "ab?", false, false, { '', 'x', 'y' } },
+ { "f v2v v3v w2w ", "([vw])2%1", false, false, { 'f ', ' v3v ', ' ' } },
+ { "", "", false, false, {} },
+ { "", "a", false, false, { '' } },
+ { "x*yz*oo*l", "*", true, false, { 'x', 'yz', 'oo', 'l' } },
}
for _, t in ipairs(tests) do
- eq(t[4], split(t[1], t[2], t[3]))
+ eq(t[5], split(t[1], t[2], {plain=t[3], trimempty=t[4]}))
end
+ -- Test old signature
+ eq({'x', 'yz', 'oo', 'l'}, split("x*yz*oo*l", "*", true))
+
local loops = {
{ "abc", ".-" },
}
@@ -283,9 +288,8 @@ describe('lua stdlib', function()
vim/shared.lua:0: in function <vim/shared.lua:0>]]),
pcall_err(split, 'string', 1))
eq(dedent([[
- Error executing lua: vim/shared.lua:0: plain: expected boolean, got number
+ Error executing lua: vim/shared.lua:0: kwargs: expected table, got number
stack traceback:
- vim/shared.lua:0: in function 'gsplit'
vim/shared.lua:0: in function <vim/shared.lua:0>]]),
pcall_err(split, 'string', 'string', 1))
end)