aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ci/build.ps19
-rw-r--r--runtime/autoload/provider/clipboard.vim8
-rw-r--r--runtime/doc/indent.txt8
-rw-r--r--runtime/doc/options.txt4
-rw-r--r--runtime/doc/treesitter.txt9
-rw-r--r--runtime/lua/vim/lsp/protocol.lua13
-rw-r--r--runtime/lua/vim/lsp/rpc.lua19
-rw-r--r--runtime/lua/vim/lsp/util.lua22
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua2
-rwxr-xr-xscripts/vim-patch.sh12
-rw-r--r--src/nvim/api/buffer.c6
-rw-r--r--src/nvim/api/private/helpers.c34
-rw-r--r--src/nvim/api/private/helpers.h3
-rw-r--r--src/nvim/api/vim.c114
-rw-r--r--src/nvim/api/window.c4
-rw-r--r--src/nvim/buffer.c235
-rw-r--r--src/nvim/buffer_defs.h29
-rw-r--r--src/nvim/change.c6
-rw-r--r--src/nvim/cursor.c2
-rw-r--r--src/nvim/diff.c4
-rw-r--r--src/nvim/edit.c6
-rw-r--r--src/nvim/ex_cmds.c6
-rw-r--r--src/nvim/ex_cmds2.c3
-rw-r--r--src/nvim/ex_docmd.c67
-rw-r--r--src/nvim/ex_getln.c2
-rw-r--r--src/nvim/ex_session.c6
-rw-r--r--src/nvim/extmark_defs.h5
-rw-r--r--src/nvim/fold.c2
-rw-r--r--src/nvim/globals.h10
-rw-r--r--src/nvim/highlight.c213
-rw-r--r--src/nvim/highlight_defs.h15
-rw-r--r--src/nvim/indent.c17
-rw-r--r--src/nvim/indent_c.c16
-rw-r--r--src/nvim/lua/executor.c27
-rw-r--r--src/nvim/lua/treesitter.c32
-rw-r--r--src/nvim/lua/vim.lua93
-rw-r--r--src/nvim/main.c2
-rw-r--r--src/nvim/map.c18
-rw-r--r--src/nvim/map.h2
-rw-r--r--src/nvim/menu.c2
-rw-r--r--src/nvim/message.c4
-rw-r--r--src/nvim/mouse.c4
-rw-r--r--src/nvim/move.c41
-rw-r--r--src/nvim/msgpack_rpc/channel.c6
-rw-r--r--src/nvim/normal.c20
-rw-r--r--src/nvim/ops.c2
-rw-r--r--src/nvim/option.c23
-rw-r--r--src/nvim/option_defs.h3
-rw-r--r--src/nvim/os/os_defs.h5
-rw-r--r--src/nvim/popupmnu.c2
-rw-r--r--src/nvim/quickfix.c2
-rw-r--r--src/nvim/screen.c67
-rw-r--r--src/nvim/search.c2
-rw-r--r--src/nvim/spell.c4
-rw-r--r--src/nvim/spell_defs.h1
-rw-r--r--src/nvim/spellfile.c35
-rw-r--r--src/nvim/syntax.c94
-rw-r--r--src/nvim/tag.c2
-rw-r--r--src/nvim/terminal.c4
-rw-r--r--src/nvim/testdir/test_cindent.vim36
-rw-r--r--src/nvim/testdir/test_cmdline.vim21
-rw-r--r--src/nvim/testdir/test_edit.vim7
-rw-r--r--src/nvim/testdir/test_listdict.vim4
-rw-r--r--src/nvim/testdir/test_messages.vim23
-rw-r--r--src/nvim/testdir/test_mksession.vim13
-rw-r--r--src/nvim/testdir/test_options.vim1
-rw-r--r--src/nvim/testdir/test_registers.vim69
-rw-r--r--src/nvim/testdir/test_ruby.vim69
-rw-r--r--src/nvim/testdir/test_statusline.vim15
-rw-r--r--src/nvim/types.h2
-rw-r--r--src/nvim/ui_compositor.c1
-rw-r--r--src/nvim/undo.c2
-rw-r--r--src/nvim/vim.h1
-rw-r--r--src/nvim/window.c68
-rw-r--r--test/functional/core/startup_spec.lua22
-rw-r--r--test/functional/eval/null_spec.lua2
-rw-r--r--test/functional/ex_cmds/packadd_spec.lua74
-rw-r--r--test/functional/fixtures/pack/foo/opt/bonus/autoload/bonus.vim3
-rw-r--r--test/functional/fixtures/pack/foo/opt/bonus/lua/bonus.lua1
-rw-r--r--test/functional/fixtures/pack/foo/start/bar/autoload/bar.vim3
-rw-r--r--test/functional/fixtures/pack/foo/start/bar/lua/bar.lua1
-rw-r--r--test/functional/helpers.lua8
-rw-r--r--test/functional/legacy/055_list_and_dict_types_spec.lua4
-rw-r--r--test/functional/legacy/cmdline_spec.lua66
-rw-r--r--test/functional/lua/overrides_spec.lua113
-rw-r--r--test/functional/lua/treesitter_spec.lua22
-rw-r--r--test/functional/ui/cmdline_spec.lua32
-rw-r--r--test/functional/ui/decorations_spec.lua142
-rw-r--r--test/functional/ui/screen.lua4
-rw-r--r--test/unit/buffer_spec.lua40
-rw-r--r--third-party/cmake/GetBinaryDeps.cmake1
91 files changed, 1447 insertions, 831 deletions
diff --git a/ci/build.ps1 b/ci/build.ps1
index 08fc76393d..dbc43aecf3 100644
--- a/ci/build.ps1
+++ b/ci/build.ps1
@@ -91,7 +91,14 @@ if ($compiler -eq 'MINGW') {
& C:\msys64\usr\bin\mkdir -p /var/cache/pacman/pkg
# Build third-party dependencies
- C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm -Su" ; exitIfFailed
+ C:\msys64\usr\bin\bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" ; exitIfFailed
+ C:\msys64\usr\bin\bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" ; exitIfFailed
+ C:\msys64\usr\bin\bash -lc "pacman-key --verify msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" ; exitIfFailed
+ C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm -U msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" ; exitIfFailed
+ # If there are still processes using msys-2.0.dll, after the base system update is finished, it will wait for input from the user.
+ # To prevent this, we will terminate all processes that use msys-2.0.dll.
+ Get-Process | Where-Object { $_.path -like 'C:\msys64*' } | Stop-Process
+ C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm -Syu" ; exitIfFailed
C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm --needed -S $mingwPackages" ; exitIfFailed
}
elseif ($compiler -eq 'MSVC') {
diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim
index 275d18a5a9..c2195fa02d 100644
--- a/runtime/autoload/provider/clipboard.vim
+++ b/runtime/autoload/provider/clipboard.vim
@@ -91,19 +91,19 @@ function! provider#clipboard#Executable() abort
let s:paste['*'] = s:paste['+']
let s:cache_enabled = 0
return 'pbcopy'
- elseif exists('$WAYLAND_DISPLAY') && executable('wl-copy') && executable('wl-paste')
+ elseif !empty($WAYLAND_DISPLAY) && executable('wl-copy') && executable('wl-paste')
let s:copy['+'] = ['wl-copy', '--foreground', '--type', 'text/plain']
let s:paste['+'] = ['wl-paste', '--no-newline']
let s:copy['*'] = ['wl-copy', '--foreground', '--primary', '--type', 'text/plain']
let s:paste['*'] = ['wl-paste', '--no-newline', '--primary']
return 'wl-copy'
- elseif exists('$DISPLAY') && executable('xclip')
+ elseif !empty($DISPLAY) && executable('xclip')
let s:copy['+'] = ['xclip', '-quiet', '-i', '-selection', 'clipboard']
let s:paste['+'] = ['xclip', '-o', '-selection', 'clipboard']
let s:copy['*'] = ['xclip', '-quiet', '-i', '-selection', 'primary']
let s:paste['*'] = ['xclip', '-o', '-selection', 'primary']
return 'xclip'
- elseif exists('$DISPLAY') && executable('xsel') && s:cmd_ok('xsel -o -b')
+ elseif !empty($DISPLAY) && executable('xsel') && s:cmd_ok('xsel -o -b')
let s:copy['+'] = ['xsel', '--nodetach', '-i', '-b']
let s:paste['+'] = ['xsel', '-o', '-b']
let s:copy['*'] = ['xsel', '--nodetach', '-i', '-p']
@@ -132,7 +132,7 @@ function! provider#clipboard#Executable() abort
let s:copy['*'] = s:copy['+']
let s:paste['*'] = s:paste['+']
return 'win32yank'
- elseif exists('$TMUX') && executable('tmux')
+ elseif !empty($TMUX) && executable('tmux')
let s:copy['+'] = ['tmux', 'load-buffer', '-']
let s:paste['+'] = ['tmux', 'save-buffer', '-']
let s:copy['*'] = s:copy['+']
diff --git a/runtime/doc/indent.txt b/runtime/doc/indent.txt
index 1df0331239..f2278f8453 100644
--- a/runtime/doc/indent.txt
+++ b/runtime/doc/indent.txt
@@ -566,9 +566,15 @@ The examples below assume a 'shiftwidth' of 4.
with "#" does not work.
+ PN When N is non-zero recognize C pragmas, and indent them like any
+ other code; does not concern other preprocessor directives.
+ When N is zero (default): don't recognize C pragmas, treating
+ them like every other preprocessor directive.
+
+
The defaults, spelled out in full, are:
cinoptions=>s,e0,n0,f0,{0,}0,^0,L-1,:s,=s,l0,b0,gs,hs,N0,E0,ps,ts,is,+s,
- c3,C0,/0,(2s,us,U0,w0,W0,k0,m0,j0,J0,)20,*70,#0
+ c3,C0,/0,(2s,us,U0,w0,W0,k0,m0,j0,J0,)20,*70,#0,P0
Vim puts a line in column 1 if:
- It starts with '#' (preprocessor directives), if 'cinkeys' contains '#0'.
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 448df31798..b83d2c4484 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -2918,6 +2918,8 @@ A jump table for the options with a short description can be found at |Q_op|.
*'go-c'*
'c' Use console dialogs instead of popup dialogs for simple
choices.
+ *'go-d'*
+ 'd' Use dark theme variant if available.
*'go-e'*
'e' Add tab pages when indicated with 'showtabline'.
'guitablabel' can be used to change the text in the labels.
@@ -5795,7 +5797,7 @@ A jump table for the options with a short description can be found at |Q_op|.
normal text. Each status line item is of the form:
%-0{minwid}.{maxwid}{item}
All fields except the {item} are optional. A single percent sign can
- be given as "%%". Up to 80 items can be specified. *E541*
+ be given as "%%".
When the option starts with "%!" then it is used as an expression,
evaluated and the result is used as the option value. Example: >
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 7f644486f7..aaf13d1640 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -136,6 +136,15 @@ tsnode:has_error() *tsnode:has_error()*
tsnode:sexpr() *tsnode:sexpr()*
Get an S-expression representing the node as a string.
+tsnode:id() *tsnode:id()*
+ Get an unique identier for the node inside its own tree.
+
+ No guarantees are made about this identifer's internal representation,
+ except for being a primitive lua type with value equality (so not a table).
+ Presently it is a (non-printable) string.
+
+ NB: the id is not guaranteed to be unique for nodes from different trees.
+
tsnode:descendant_for_range({start_row}, {start_col}, {end_row}, {end_col})
*tsnode:descendant_for_range()*
Get the smallest node within this node that spans the given range of
diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua
index 2773f59b45..70862320c5 100644
--- a/runtime/lua/vim/lsp/protocol.lua
+++ b/runtime/lua/vim/lsp/protocol.lua
@@ -632,15 +632,18 @@ function protocol.make_client_capabilities()
codeActionLiteralSupport = {
codeActionKind = {
- valueSet = {};
+ valueSet = vim.tbl_values(protocol.CodeActionKind);
};
};
};
completion = {
dynamicRegistration = false;
completionItem = {
+ -- Until we can actually expand snippet, move cursor and allow for true snippet experience,
+ -- this should be disabled out of the box.
+ -- However, users can turn this back on if they have a snippet plugin.
+ snippetSupport = false;
- snippetSupport = true;
commitCharactersSupport = false;
preselectSupport = false;
deprecatedSupport = false;
@@ -940,11 +943,9 @@ function protocol.resolve_capabilities(server_capabilities)
if server_capabilities.codeActionProvider == nil then
general_properties.code_action = false
- elseif type(server_capabilities.codeActionProvider) == 'boolean' then
+ elseif type(server_capabilities.codeActionProvider) == 'boolean'
+ or type(server_capabilities.codeActionProvider) == 'table' then
general_properties.code_action = server_capabilities.codeActionProvider
- elseif type(server_capabilities.codeActionProvider) == 'table' then
- -- TODO(ashkan) support CodeActionKind
- general_properties.code_action = false
else
error("The server sent invalid codeActionProvider")
end
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index 749a51fecc..17c411f952 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -42,13 +42,28 @@ local function is_dir(filename)
end
local NIL = vim.NIL
+
+--@private
+local recursive_convert_NIL
+recursive_convert_NIL = function(v, tbl_processed)
+ if v == NIL then
+ return nil
+ elseif not tbl_processed[v] and type(v) == 'table' then
+ tbl_processed[v] = true
+ return vim.tbl_map(function(x)
+ return recursive_convert_NIL(x, tbl_processed)
+ end, v)
+ end
+
+ return v
+end
+
--@private
--- Returns its argument, but converts `vim.NIL` to Lua `nil`.
--@param v (any) Argument
--@returns (any)
local function convert_NIL(v)
- if v == NIL then return nil end
- return v
+ return recursive_convert_NIL(v, {})
end
--@private
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 775932c7fd..9ed19b938d 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -214,13 +214,16 @@ end
function M.apply_text_document_edit(text_document_edit)
local text_document = text_document_edit.textDocument
local bufnr = vim.uri_to_bufnr(text_document.uri)
- if text_document.version then
- -- `VersionedTextDocumentIdentifier`s version may be null https://microsoft.github.io/language-server-protocol/specification#versionedTextDocumentIdentifier
- if text_document.version ~= vim.NIL and M.buf_versions[bufnr] ~= nil and M.buf_versions[bufnr] > text_document.version then
- print("Buffer ", text_document.uri, " newer than edits.")
- return
- end
+
+ -- `VersionedTextDocumentIdentifier`s version may be null
+ -- https://microsoft.github.io/language-server-protocol/specification#versionedTextDocumentIdentifier
+ if text_document.version
+ and M.buf_versions[bufnr]
+ and M.buf_versions[bufnr] > text_document.version then
+ print("Buffer ", text_document.uri, " newer than edits.")
+ return
end
+
M.apply_text_edits(text_document_edit.edits, bufnr)
end
@@ -492,10 +495,7 @@ function M.convert_signature_help_to_markdown_lines(signature_help)
--=== 0`. Whenever possible implementors should make an active decision about
--the active signature and shouldn't rely on a default value.
local contents = {}
- local active_signature = signature_help.activeSignature
- if active_signature == vim.NIL or active_signature == nil then
- active_signature = 0
- end
+ local active_signature = signature_help.activeSignature or 0
-- If the activeSignature is not inside the valid range, then clip it.
if active_signature >= #signature_help.signatures then
active_signature = 0
@@ -535,7 +535,7 @@ function M.convert_signature_help_to_markdown_lines(signature_help)
}
--]=]
-- TODO highlight parameter
- if parameter.documentation and parameter.documentation ~= vim.NIL then
+ if parameter.documentation then
M.convert_input_to_markdown_lines(parameter.documentation, contents)
end
end
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index decde08019..6714bb6354 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -157,7 +157,7 @@ local function on_line_impl(self, buf, line)
a.nvim_buf_set_extmark(buf, ns, start_row, start_col,
{ end_line = end_row, end_col = end_col,
hl_group = hl,
- ephemeral = true
+ ephemeral = true,
})
end
if start_row > line then
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 8287958ab5..551b8fb691 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -211,6 +211,18 @@ preprocess_patch() {
LC_ALL=C sed -e 's/\( [ab]\/src\)/\1\/nvim/g' \
"$file" > "$file".tmp && mv "$file".tmp "$file"
+ # Rename evalfunc.c to eval/funcs.c
+ LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/evalfunc\.c/\1\/eval\/funcs\.c/g' \
+ "$file" > "$file".tmp && mv "$file".tmp "$file"
+
+ # Rename userfunc.c to eval/userfunc.c
+ LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/userfunc\.c/\1\/eval\/userfunc\.c/g' \
+ "$file" > "$file".tmp && mv "$file".tmp "$file"
+
+ # Rename session.c to ex_session.c
+ LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/session\(\.[ch]\)/\1\/ex_session\2/g' \
+ "$file" > "$file".tmp && mv "$file".tmp "$file"
+
# Rename test_urls.vim to check_urls.vim
LC_ALL=C sed -e 's@\( [ab]\)/runtime/doc/test\(_urls.vim\)@\1/scripts/check\2@g' \
"$file" > "$file".tmp && mv "$file".tmp "$file"
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index cad4c8314f..4569ebc713 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -974,9 +974,9 @@ void nvim_buf_delete(Buffer buffer, Dictionary opts, Error *err)
String k = opts.items[i].key;
Object v = opts.items[i].value;
if (strequal("force", k.data)) {
- force = api_coerce_to_bool(v, "force", false, err);
+ force = api_object_to_bool(v, "force", false, err);
} else if (strequal("unload", k.data)) {
- unload = api_coerce_to_bool(v, "unload", false, err);
+ unload = api_object_to_bool(v, "unload", false, err);
} else {
api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
return;
@@ -1441,7 +1441,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
goto error;
}
} else if (strequal("ephemeral", k.data)) {
- ephemeral = api_coerce_to_bool(*v, "ephemeral", false, err);
+ ephemeral = api_object_to_bool(*v, "ephemeral", false, err);
if (ERROR_SET(err)) {
goto error;
}
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 981d41ae6e..a9b1676879 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -1625,11 +1625,8 @@ free_exit:
/// @param what The name of the object, used for error message
/// @param nil_value What to return if the type is nil.
/// @param err Set if there was an error in converting to a bool
-bool api_coerce_to_bool(
- Object obj,
- const char *what,
- bool nil_value,
- Error *err)
+bool api_object_to_bool(Object obj, const char *what,
+ bool nil_value, Error *err)
{
if (obj.type == kObjectTypeBoolean) {
return obj.data.boolean;
@@ -1654,3 +1651,30 @@ const char *describe_ns(NS ns_id)
})
return "(UNKNOWN PLUGIN)";
}
+
+DecorationProvider *get_provider(NS ns_id, bool force)
+{
+ ssize_t i;
+ for (i = 0; i < (ssize_t)kv_size(decoration_providers); i++) {
+ DecorationProvider *item = &kv_A(decoration_providers, i);
+ if (item->ns_id == ns_id) {
+ return item;
+ } else if (item->ns_id > ns_id) {
+ break;
+ }
+ }
+
+ if (!force) {
+ return NULL;
+ }
+
+ for (ssize_t j = (ssize_t)kv_size(decoration_providers)-1; j >= i; j++) {
+ // allocates if needed:
+ (void)kv_a(decoration_providers, (size_t)j+1);
+ kv_A(decoration_providers, (size_t)j+1) = kv_A(decoration_providers, j);
+ }
+ DecorationProvider *item = &kv_a(decoration_providers, (size_t)i);
+ *item = DECORATION_PROVIDER_INIT(ns_id);
+
+ return item;
+}
diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h
index df3a263dcf..7c6f07402b 100644
--- a/src/nvim/api/private/helpers.h
+++ b/src/nvim/api/private/helpers.h
@@ -52,7 +52,8 @@
.type = kObjectTypeLuaRef, \
.data.luaref = r })
-#define NIL ((Object) {.type = kObjectTypeNil})
+#define NIL ((Object)OBJECT_INIT)
+#define NULL_STRING ((String)STRING_INIT)
#define PUT(dict, k, v) \
kv_push(dict, ((KeyValuePair) { .key = cstr_to_string(k), .value = v }))
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 876b052a8e..725847886a 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -199,6 +199,69 @@ Integer nvim_get_hl_id_by_name(String name)
return syn_check_group((const char_u *)name.data, (int)name.size);
}
+Dictionary nvim__get_hl_defs(Integer ns_id, Error *err)
+{
+ if (ns_id == 0) {
+ return get_global_hl_defs();
+ }
+ abort();
+}
+
+/// Set a highlight group.
+///
+/// @param ns_id number of namespace for this highlight
+/// @param name highlight group name, like ErrorMsg
+/// @param val highlight definiton map, like |nvim_get_hl_by_name|.
+/// @param[out] err Error details, if any
+///
+/// TODO: ns_id = 0, should modify :highlight namespace
+/// TODO val should take update vs reset flag
+void nvim_set_hl(Integer ns_id, String name, Dictionary val, Error *err)
+ FUNC_API_SINCE(7)
+{
+ int hl_id = syn_check_group( (char_u *)(name.data), (int)name.size);
+ int link_id = -1;
+
+ HlAttrs attrs = dict2hlattrs(val, true, &link_id, err);
+ if (!ERROR_SET(err)) {
+ ns_hl_def((NS)ns_id, hl_id, attrs, link_id);
+ }
+}
+
+/// Set active namespace for highlights.
+///
+/// NB: this function can be called from async contexts, but the
+/// semantics are not yet well-defined. To start with
+/// |nvim_set_decoration_provider| on_win and on_line callbacks
+/// are explicitly allowed to change the namespace during a redraw cycle.
+///
+/// @param ns_id the namespace to activate
+/// @param[out] err Error details, if any
+void nvim_set_hl_ns(Integer ns_id, Error *err)
+ FUNC_API_SINCE(7)
+ FUNC_API_FAST
+{
+ if (ns_id >= 0) {
+ ns_hl_active = (NS)ns_id;
+ }
+
+ // TODO(bfredl): this is a little bit hackish. Eventually we want a standard
+ // event path for redraws caused by "fast" events. This could tie in with
+ // better throttling of async events causing redraws, such as non-batched
+ // nvim_buf_set_extmark calls from async contexts.
+ if (!updating_screen && !ns_hl_changed) {
+ multiqueue_put(main_loop.events, on_redraw_event, 0);
+ }
+ ns_hl_changed = true;
+}
+
+static void on_redraw_event(void **argv)
+ FUNC_API_NOEXPORT
+{
+ redraw_all_later(NOT_VALID);
+}
+
+
/// Sends input-keys to Nvim, subject to various quirks controlled by `mode`
/// flags. This is a blocking call, unlike |nvim_input()|.
///
@@ -678,7 +741,11 @@ Integer nvim_strwidth(String text, Error *err)
ArrayOf(String) nvim_list_runtime_paths(void)
FUNC_API_SINCE(1)
{
+ // TODO(bfredl): this should just work:
+ // return nvim_get_runtime_file(NULL_STRING, true);
+
Array rv = ARRAY_DICT_INIT;
+
char_u *rtp = p_rtp;
if (*rtp == NUL) {
@@ -725,22 +792,29 @@ ArrayOf(String) nvim_list_runtime_paths(void)
/// @param name pattern of files to search for
/// @param all whether to return all matches or only the first
/// @return list of absolute paths to the found files
-ArrayOf(String) nvim_get_runtime_file(String name, Boolean all)
+ArrayOf(String) nvim_get_runtime_file(String name, Boolean all, Error *err)
FUNC_API_SINCE(7)
{
Array rv = ARRAY_DICT_INIT;
- if (!name.data) {
+
+ // TODO(bfredl):
+ if (name.size == 0) {
+ api_set_error(err, kErrorTypeValidation, "not yet implemented");
return rv;
}
+
int flags = DIP_START | (all ? DIP_ALL : 0);
- do_in_runtimepath((char_u *)name.data, flags, find_runtime_cb, &rv);
+ do_in_runtimepath(name.size ? (char_u *)name.data : NULL,
+ flags, find_runtime_cb, &rv);
return rv;
}
static void find_runtime_cb(char_u *fname, void *cookie)
{
Array *rv = (Array *)cookie;
- ADD(*rv, STRING_OBJ(cstr_to_string((char *)fname)));
+ if (fname != NULL) {
+ ADD(*rv, STRING_OBJ(cstr_to_string((char *)fname)));
+ }
}
String nvim__get_lib_dir(void)
@@ -1477,7 +1551,7 @@ void nvim_unsubscribe(uint64_t channel_id, String event)
Integer nvim_get_color_by_name(String name)
FUNC_API_SINCE(1)
{
- return name_to_color((char_u *)name.data);
+ return name_to_color(name.data);
}
/// Returns a map of color names and RGB values.
@@ -2610,33 +2684,6 @@ void nvim__screenshot(String path)
ui_call_screenshot(path);
}
-static DecorationProvider *get_provider(NS ns_id, bool force)
-{
- ssize_t i;
- for (i = 0; i < (ssize_t)kv_size(decoration_providers); i++) {
- DecorationProvider *item = &kv_A(decoration_providers, i);
- if (item->ns_id == ns_id) {
- return item;
- } else if (item->ns_id > ns_id) {
- break;
- }
- }
-
- if (!force) {
- return NULL;
- }
-
- for (ssize_t j = (ssize_t)kv_size(decoration_providers)-1; j >= i; j++) {
- // allocates if needed:
- (void)kv_a(decoration_providers, (size_t)j+1);
- kv_A(decoration_providers, (size_t)j+1) = kv_A(decoration_providers, j);
- }
- DecorationProvider *item = &kv_a(decoration_providers, (size_t)i);
- *item = DECORATION_PROVIDER_INIT(ns_id);
-
- return item;
-}
-
static void clear_provider(DecorationProvider *p)
{
NLUA_CLEAR_REF(p->redraw_start);
@@ -2695,7 +2742,7 @@ void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts,
clear_provider(p);
// regardless of what happens, it seems good idea to redraw
- redraw_later(NOT_VALID); // TODO(bfredl): too soon?
+ redraw_all_later(NOT_VALID); // TODO(bfredl): too soon?
struct {
const char *name;
@@ -2706,6 +2753,7 @@ void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts,
{ "on_win", &p->redraw_win },
{ "on_line", &p->redraw_line },
{ "on_end", &p->redraw_end },
+ { "_on_hl_def", &p->hl_def },
{ NULL, NULL },
};
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index ba43bc6cb2..f09a03f592 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -142,7 +142,7 @@ void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err)
// make sure cursor is in visible range even if win != curwin
update_topline_win(win);
- redraw_win_later(win, VALID);
+ redraw_later(win, VALID);
}
/// Gets the window height
@@ -471,7 +471,7 @@ void nvim_win_set_config(Window window, Dictionary config, Error *err)
if (!win_new_float(win, fconfig, err)) {
return;
}
- redraw_later(NOT_VALID);
+ redraw_later(win, NOT_VALID);
} else {
win_config_float(win, fconfig);
win->w_pos_changed = true;
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 8f631ae13b..469542ec9f 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -1623,7 +1623,7 @@ void enter_buffer(buf_T *buf)
}
curbuf->b_last_used = time(NULL);
- redraw_later(NOT_VALID);
+ redraw_later(curwin, NOT_VALID);
}
// Change to the directory of the current buffer.
@@ -3440,31 +3440,17 @@ int build_stl_str_hl(
int use_sandbox,
char_u fillchar,
int maxwidth,
- struct stl_hlrec *hltab,
- StlClickRecord *tabtab
+ stl_hlrec_t **hltab,
+ StlClickRecord **tabtab
)
{
- int groupitems[STL_MAX_ITEM];
- struct stl_item {
- // Where the item starts in the status line output buffer
- char_u *start;
- // Function to run for ClickFunc items.
- char *cmd;
- // The minimum width of the item
- int minwid;
- // The maximum width of the item
- int maxwid;
- enum {
- Normal,
- Empty,
- Group,
- Separate,
- Highlight,
- TabPage,
- ClickFunc,
- Trunc
- } type;
- } items[STL_MAX_ITEM];
+ static size_t stl_items_len = 20; // Initial value, grows as needed.
+ static stl_item_t *stl_items = NULL;
+ static int *stl_groupitems = NULL;
+ static stl_hlrec_t *stl_hltab = NULL;
+ static StlClickRecord *stl_tabtab = NULL;
+ static int *stl_separator_locations = NULL;
+
#define TMPLEN 70
char_u buf_tmp[TMPLEN];
char_u win_tmp[TMPLEN];
@@ -3472,6 +3458,14 @@ int build_stl_str_hl(
const int save_must_redraw = must_redraw;
const int save_redr_type = curwin->w_redr_type;
+ if (stl_items == NULL) {
+ stl_items = xmalloc(sizeof(stl_item_t) * stl_items_len);
+ stl_groupitems = xmalloc(sizeof(int) * stl_items_len);
+ stl_hltab = xmalloc(sizeof(stl_hlrec_t) * stl_items_len);
+ stl_tabtab = xmalloc(sizeof(stl_hlrec_t) * stl_items_len);
+ stl_separator_locations = xmalloc(sizeof(int) * stl_items_len);
+ }
+
// When the format starts with "%!" then evaluate it as an expression and
// use the result as the actual format string.
if (fmt[0] == '%' && fmt[1] == '!') {
@@ -3540,14 +3534,17 @@ int build_stl_str_hl(
// Proceed character by character through the statusline format string
// fmt_p is the current positon in the input buffer
for (char_u *fmt_p = usefmt; *fmt_p; ) {
- if (curitem == STL_MAX_ITEM) {
- // There are too many items. Add the error code to the statusline
- // to give the user a hint about what went wrong.
- if (out_p + 5 < out_end_p) {
- memmove(out_p, " E541", (size_t)5);
- out_p += 5;
- }
- break;
+ if (curitem == (int)stl_items_len) {
+ size_t new_len = stl_items_len * 3 / 2;
+
+ stl_items = xrealloc(stl_items, sizeof(stl_item_t) * new_len);
+ stl_groupitems = xrealloc(stl_groupitems, sizeof(int) * new_len);
+ stl_hltab = xrealloc(stl_hltab, sizeof(stl_hlrec_t) * new_len);
+ stl_tabtab = xrealloc(stl_tabtab, sizeof(StlClickRecord) * new_len);
+ stl_separator_locations =
+ xrealloc(stl_separator_locations, sizeof(int) * new_len);
+
+ stl_items_len = new_len;
}
if (*fmt_p != NUL && *fmt_p != '%') {
@@ -3591,16 +3588,16 @@ int build_stl_str_hl(
if (groupdepth > 0) {
continue;
}
- items[curitem].type = Separate;
- items[curitem++].start = out_p;
+ stl_items[curitem].type = Separate;
+ stl_items[curitem++].start = out_p;
continue;
}
// STL_TRUNCMARK: Where to begin truncating if the statusline is too long.
if (*fmt_p == STL_TRUNCMARK) {
fmt_p++;
- items[curitem].type = Trunc;
- items[curitem++].start = out_p;
+ stl_items[curitem].type = Trunc;
+ stl_items[curitem++].start = out_p;
continue;
}
@@ -3616,7 +3613,7 @@ int build_stl_str_hl(
// Determine how long the group is.
// Note: We set the current output position to null
// so `vim_strsize` will work.
- char_u *t = items[groupitems[groupdepth]].start;
+ char_u *t = stl_items[stl_groupitems[groupdepth]].start;
*out_p = NUL;
long group_len = vim_strsize(t);
@@ -3626,40 +3623,40 @@ int build_stl_str_hl(
// move the output pointer back to where the group started.
// Note: This erases any non-item characters that were in the group.
// Otherwise there would be no reason to do this step.
- if (curitem > groupitems[groupdepth] + 1
- && items[groupitems[groupdepth]].minwid == 0) {
+ if (curitem > stl_groupitems[groupdepth] + 1
+ && stl_items[stl_groupitems[groupdepth]].minwid == 0) {
// remove group if all items are empty and highlight group
// doesn't change
int group_start_userhl = 0;
int group_end_userhl = 0;
int n;
- for (n = groupitems[groupdepth] - 1; n >= 0; n--) {
- if (items[n].type == Highlight) {
- group_start_userhl = group_end_userhl = items[n].minwid;
+ for (n = stl_groupitems[groupdepth] - 1; n >= 0; n--) {
+ if (stl_items[n].type == Highlight) {
+ group_start_userhl = group_end_userhl = stl_items[n].minwid;
break;
}
}
- for (n = groupitems[groupdepth] + 1; n < curitem; n++) {
- if (items[n].type == Normal) {
+ for (n = stl_groupitems[groupdepth] + 1; n < curitem; n++) {
+ if (stl_items[n].type == Normal) {
break;
}
- if (items[n].type == Highlight) {
- group_end_userhl = items[n].minwid;
+ if (stl_items[n].type == Highlight) {
+ group_end_userhl = stl_items[n].minwid;
}
}
if (n == curitem && group_start_userhl == group_end_userhl) {
// empty group
out_p = t;
group_len = 0;
- for (n = groupitems[groupdepth] + 1; n < curitem; n++) {
+ for (n = stl_groupitems[groupdepth] + 1; n < curitem; n++) {
// do not use the highlighting from the removed group
- if (items[n].type == Highlight) {
- items[n].type = Empty;
+ if (stl_items[n].type == Highlight) {
+ stl_items[n].type = Empty;
}
// adjust the start position of TabPage to the next
// item position
- if (items[n].type == TabPage) {
- items[n].start = out_p;
+ if (stl_items[n].type == TabPage) {
+ stl_items[n].start = out_p;
}
}
}
@@ -3667,18 +3664,19 @@ int build_stl_str_hl(
// If the group is longer than it is allowed to be
// truncate by removing bytes from the start of the group text.
- if (group_len > items[groupitems[groupdepth]].maxwid) {
+ if (group_len > stl_items[stl_groupitems[groupdepth]].maxwid) {
// { Determine the number of bytes to remove
long n;
if (has_mbyte) {
// Find the first character that should be included.
n = 0;
- while (group_len >= items[groupitems[groupdepth]].maxwid) {
+ while (group_len >= stl_items[stl_groupitems[groupdepth]].maxwid) {
group_len -= ptr2cells(t + n);
n += (*mb_ptr2len)(t + n);
}
} else {
- n = (long)(out_p - t) - items[groupitems[groupdepth]].maxwid + 1;
+ n = (long)(out_p - t)
+ - stl_items[stl_groupitems[groupdepth]].maxwid + 1;
}
// }
@@ -3689,25 +3687,26 @@ int build_stl_str_hl(
memmove(t + 1, t + n, (size_t)(out_p - (t + n)));
out_p = out_p - n + 1;
// Fill up space left over by half a double-wide char.
- while (++group_len < items[groupitems[groupdepth]].minwid) {
+ while (++group_len < stl_items[stl_groupitems[groupdepth]].minwid) {
*out_p++ = fillchar;
}
// }
// correct the start of the items for the truncation
- for (int idx = groupitems[groupdepth] + 1; idx < curitem; idx++) {
+ for (int idx = stl_groupitems[groupdepth] + 1; idx < curitem; idx++) {
// Shift everything back by the number of removed bytes
- items[idx].start -= n;
+ stl_items[idx].start -= n;
// If the item was partially or completely truncated, set its
// start to the start of the group
- if (items[idx].start < t) {
- items[idx].start = t;
+ if (stl_items[idx].start < t) {
+ stl_items[idx].start = t;
}
}
// If the group is shorter than the minimum width, add padding characters.
- } else if (abs(items[groupitems[groupdepth]].minwid) > group_len) {
- long min_group_width = items[groupitems[groupdepth]].minwid;
+ } else if (
+ abs(stl_items[stl_groupitems[groupdepth]].minwid) > group_len) {
+ long min_group_width = stl_items[stl_groupitems[groupdepth]].minwid;
// If the group is left-aligned, add characters to the right.
if (min_group_width < 0) {
min_group_width = 0 - min_group_width;
@@ -3726,8 +3725,8 @@ int build_stl_str_hl(
// }
// Adjust item start positions
- for (int n = groupitems[groupdepth] + 1; n < curitem; n++) {
- items[n].start += group_len;
+ for (int n = stl_groupitems[groupdepth] + 1; n < curitem; n++) {
+ stl_items[n].start += group_len;
}
// Prepend the fill characters
@@ -3763,9 +3762,9 @@ int build_stl_str_hl(
// User highlight groups override the min width field
// to denote the styling to use.
if (*fmt_p == STL_USER_HL) {
- items[curitem].type = Highlight;
- items[curitem].start = out_p;
- items[curitem].minwid = minwid > 9 ? 1 : minwid;
+ stl_items[curitem].type = Highlight;
+ stl_items[curitem].start = out_p;
+ stl_items[curitem].minwid = minwid > 9 ? 1 : minwid;
fmt_p++;
curitem++;
continue;
@@ -3799,8 +3798,8 @@ int build_stl_str_hl(
if (minwid == 0) {
// %X ends the close label, go back to the previous tab label nr.
for (long n = curitem - 1; n >= 0; n--) {
- if (items[n].type == TabPage && items[n].minwid >= 0) {
- minwid = items[n].minwid;
+ if (stl_items[n].type == TabPage && stl_items[n].minwid >= 0) {
+ minwid = stl_items[n].minwid;
break;
}
}
@@ -3809,9 +3808,9 @@ int build_stl_str_hl(
minwid = -minwid;
}
}
- items[curitem].type = TabPage;
- items[curitem].start = out_p;
- items[curitem].minwid = minwid;
+ stl_items[curitem].type = TabPage;
+ stl_items[curitem].start = out_p;
+ stl_items[curitem].minwid = minwid;
fmt_p++;
curitem++;
continue;
@@ -3826,10 +3825,10 @@ int build_stl_str_hl(
if (*fmt_p != STL_CLICK_FUNC) {
break;
}
- items[curitem].type = ClickFunc;
- items[curitem].start = out_p;
- items[curitem].cmd = xmemdupz(t, (size_t)(((char *)fmt_p - t)));
- items[curitem].minwid = minwid;
+ stl_items[curitem].type = ClickFunc;
+ stl_items[curitem].start = out_p;
+ stl_items[curitem].cmd = xmemdupz(t, (size_t)(((char *)fmt_p - t)));
+ stl_items[curitem].minwid = minwid;
fmt_p++;
curitem++;
continue;
@@ -3850,11 +3849,11 @@ int build_stl_str_hl(
// Denotes the start of a new group
if (*fmt_p == '(') {
- groupitems[groupdepth++] = curitem;
- items[curitem].type = Group;
- items[curitem].start = out_p;
- items[curitem].minwid = minwid;
- items[curitem].maxwid = maxwid;
+ stl_groupitems[groupdepth++] = curitem;
+ stl_items[curitem].type = Group;
+ stl_items[curitem].start = out_p;
+ stl_items[curitem].minwid = minwid;
+ stl_items[curitem].maxwid = maxwid;
fmt_p++;
curitem++;
continue;
@@ -4149,9 +4148,9 @@ int build_stl_str_hl(
// Create a highlight item based on the name
if (*fmt_p == '#') {
- items[curitem].type = Highlight;
- items[curitem].start = out_p;
- items[curitem].minwid = -syn_namen2id(t, (int)(fmt_p - t));
+ stl_items[curitem].type = Highlight;
+ stl_items[curitem].start = out_p;
+ stl_items[curitem].minwid = -syn_namen2id(t, (int)(fmt_p - t));
curitem++;
fmt_p++;
}
@@ -4162,8 +4161,8 @@ int build_stl_str_hl(
// If we made it this far, the item is normal and starts at
// our current position in the output buffer.
// Non-normal items would have `continued`.
- items[curitem].start = out_p;
- items[curitem].type = Normal;
+ stl_items[curitem].start = out_p;
+ stl_items[curitem].type = Normal;
// Copy the item string into the output buffer
if (str != NULL && *str) {
@@ -4321,7 +4320,7 @@ int build_stl_str_hl(
// Otherwise, there was nothing to print so mark the item as empty
} else {
- items[curitem].type = Empty;
+ stl_items[curitem].type = Empty;
}
// Only free the string buffer if we allocated it.
@@ -4362,13 +4361,13 @@ int build_stl_str_hl(
// Otherwise, look for the truncation item
} else {
// Default to truncating at the first item
- trunc_p = items[0].start;
+ trunc_p = stl_items[0].start;
item_idx = 0;
for (int i = 0; i < itemcnt; i++) {
- if (items[i].type == Trunc) {
- // Truncate at %< items.
- trunc_p = items[i].start;
+ if (stl_items[i].type == Trunc) {
+ // Truncate at %< stl_items.
+ trunc_p = stl_items[i].start;
item_idx = i;
break;
}
@@ -4403,7 +4402,7 @@ int build_stl_str_hl(
// Ignore any items in the statusline that occur after
// the truncation point
for (int i = 0; i < itemcnt; i++) {
- if (items[i].start > trunc_p) {
+ if (stl_items[i].start > trunc_p) {
itemcnt = i;
break;
}
@@ -4458,12 +4457,12 @@ int build_stl_str_hl(
for (int i = item_idx; i < itemcnt; i++) {
// Items starting at or after the end of the truncated section need
// to be moved backwards.
- if (items[i].start >= trunc_end_p) {
- items[i].start -= item_offset;
+ if (stl_items[i].start >= trunc_end_p) {
+ stl_items[i].start -= item_offset;
// Anything inside the truncated area is set to start
// at the `<` truncation character.
} else {
- items[i].start = trunc_p;
+ stl_items[i].start = trunc_p;
}
}
// }
@@ -4479,7 +4478,7 @@ int build_stl_str_hl(
// figuring out how many groups there are.
int num_separators = 0;
for (int i = 0; i < itemcnt; i++) {
- if (items[i].type == Separate) {
+ if (stl_items[i].type == Separate) {
num_separators++;
}
}
@@ -4488,11 +4487,10 @@ int build_stl_str_hl(
if (num_separators) {
// Create an array of the start location for each
// separator mark.
- int separator_locations[STL_MAX_ITEM];
int index = 0;
for (int i = 0; i < itemcnt; i++) {
- if (items[i].type == Separate) {
- separator_locations[index] = i;
+ if (stl_items[i].type == Separate) {
+ stl_separator_locations[index] = i;
index++;
}
}
@@ -4504,16 +4502,17 @@ int build_stl_str_hl(
for (int i = 0; i < num_separators; i++) {
int dislocation = (i == (num_separators - 1))
? final_spaces : standard_spaces;
- char_u *seploc = items[separator_locations[i]].start + dislocation;
- STRMOVE(seploc, items[separator_locations[i]].start);
- for (char_u *s = items[separator_locations[i]].start; s < seploc; s++) {
+ char_u *start = stl_items[stl_separator_locations[i]].start;
+ char_u *seploc = start + dislocation;
+ STRMOVE(seploc, start);
+ for (char_u *s = start; s < seploc; s++) {
*s = fillchar;
}
- for (int item_idx = separator_locations[i] + 1;
+ for (int item_idx = stl_separator_locations[i] + 1;
item_idx < itemcnt;
item_idx++) {
- items[item_idx].start += dislocation;
+ stl_items[item_idx].start += dislocation;
}
}
@@ -4523,11 +4522,12 @@ int build_stl_str_hl(
// Store the info about highlighting.
if (hltab != NULL) {
- struct stl_hlrec *sp = hltab;
+ *hltab = stl_hltab;
+ stl_hlrec_t *sp = stl_hltab;
for (long l = 0; l < itemcnt; l++) {
- if (items[l].type == Highlight) {
- sp->start = items[l].start;
- sp->userhl = items[l].minwid;
+ if (stl_items[l].type == Highlight) {
+ sp->start = stl_items[l].start;
+ sp->userhl = stl_items[l].minwid;
sp++;
}
}
@@ -4537,16 +4537,17 @@ int build_stl_str_hl(
// Store the info about tab pages labels.
if (tabtab != NULL) {
- StlClickRecord *cur_tab_rec = tabtab;
+ *tabtab = stl_tabtab;
+ StlClickRecord *cur_tab_rec = stl_tabtab;
for (long l = 0; l < itemcnt; l++) {
- if (items[l].type == TabPage) {
- cur_tab_rec->start = (char *)items[l].start;
- if (items[l].minwid == 0) {
+ if (stl_items[l].type == TabPage) {
+ cur_tab_rec->start = (char *)stl_items[l].start;
+ if (stl_items[l].minwid == 0) {
cur_tab_rec->def.type = kStlClickDisabled;
cur_tab_rec->def.tabnr = 0;
} else {
- int tabnr = items[l].minwid;
- if (items[l].minwid > 0) {
+ int tabnr = stl_items[l].minwid;
+ if (stl_items[l].minwid > 0) {
cur_tab_rec->def.type = kStlClickTabSwitch;
} else {
cur_tab_rec->def.type = kStlClickTabClose;
@@ -4556,11 +4557,11 @@ int build_stl_str_hl(
}
cur_tab_rec->def.func = NULL;
cur_tab_rec++;
- } else if (items[l].type == ClickFunc) {
- cur_tab_rec->start = (char *)items[l].start;
+ } else if (stl_items[l].type == ClickFunc) {
+ cur_tab_rec->start = (char *)stl_items[l].start;
cur_tab_rec->def.type = kStlClickFuncRun;
- cur_tab_rec->def.tabnr = items[l].minwid;
- cur_tab_rec->def.func = items[l].cmd;
+ cur_tab_rec->def.tabnr = stl_items[l].minwid;
+ cur_tab_rec->def.func = stl_items[l].cmd;
cur_tab_rec++;
}
}
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 8e855cb644..4efc341875 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -361,14 +361,36 @@ struct mapblock {
sctx_T m_script_ctx; // SCTX where map was defined
};
-/*
- * Used for highlighting in the status line.
- */
+/// Used for highlighting in the status line.
+typedef struct stl_hlrec stl_hlrec_t;
struct stl_hlrec {
char_u *start;
int userhl; // 0: no HL, 1-9: User HL, < 0 for syn ID
};
+/// Used for building the status line.
+typedef struct stl_item stl_item_t;
+struct stl_item {
+ // Where the item starts in the status line output buffer
+ char_u *start;
+ // Function to run for ClickFunc items.
+ char *cmd;
+ // The minimum width of the item
+ int minwid;
+ // The maximum width of the item
+ int maxwid;
+ enum {
+ Normal,
+ Empty,
+ Group,
+ Separate,
+ Highlight,
+ TabPage,
+ ClickFunc,
+ Trunc
+ } type;
+};
+
// values for b_syn_spell: what to do with toplevel text
#define SYNSPL_DEFAULT 0 // spell check if @Spell not defined
#define SYNSPL_TOP 1 // spell check toplevel text
@@ -773,6 +795,7 @@ struct file_buffer {
int b_ind_cpp_namespace;
int b_ind_if_for_while;
int b_ind_cpp_extern_c;
+ int b_ind_pragma;
linenr_T b_no_eol_lnum; /* non-zero lnum when last line of next binary
* write should not have an end-of-line */
diff --git a/src/nvim/change.c b/src/nvim/change.c
index be52750c44..9ee987b45d 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -294,7 +294,7 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume,
// change.
if (wp->w_p_rnu
|| (wp->w_p_cul && lnum <= wp->w_last_cursorline)) {
- redraw_win_later(wp, SOME_VALID);
+ redraw_later(wp, SOME_VALID);
}
}
}
@@ -348,7 +348,7 @@ void changed_bytes(linenr_T lnum, colnr_T col)
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_p_diff && wp != curwin) {
- redraw_win_later(wp, VALID);
+ redraw_later(wp, VALID);
wlnum = diff_lnum_win(lnum, wp);
if (wlnum > 0) {
changedOneline(wp->w_buffer, wlnum);
@@ -475,7 +475,7 @@ changed_lines(
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_p_diff && wp != curwin) {
- redraw_win_later(wp, VALID);
+ redraw_later(wp, VALID);
wlnum = diff_lnum_win(lnum, wp);
if (wlnum > 0) {
changed_lines_buf(wp->w_buffer, wlnum,
diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c
index 036ae32589..d3ffab1759 100644
--- a/src/nvim/cursor.c
+++ b/src/nvim/cursor.c
@@ -482,7 +482,7 @@ bool leftcol_changed(void)
if (retval)
curwin->w_set_curswant = true;
- redraw_later(NOT_VALID);
+ redraw_later(curwin, NOT_VALID);
return retval;
}
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 3de5fc49bd..b9c293f6c8 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -643,7 +643,7 @@ void diff_redraw(bool dofold)
if (!wp->w_p_diff) {
continue;
}
- redraw_win_later(wp, SOME_VALID);
+ redraw_later(wp, SOME_VALID);
if (dofold && foldmethodIsDiff(wp)) {
foldUpdateAll(wp);
}
@@ -1415,7 +1415,7 @@ void diff_win_options(win_T *wp, int addbuf)
if (addbuf) {
diff_buf_add(wp->w_buffer);
}
- redraw_win_later(wp, NOT_VALID);
+ redraw_later(wp, NOT_VALID);
}
/// Set options not to show diffs. For the current window or all windows.
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index ac0e6cc9f6..3e62ed9036 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -8571,7 +8571,7 @@ static void ins_up(
if (old_topline != curwin->w_topline
|| old_topfill != curwin->w_topfill
)
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
start_arrow(&tpos);
can_cindent = true;
} else {
@@ -8619,7 +8619,7 @@ static void ins_down(
if (old_topline != curwin->w_topline
|| old_topfill != curwin->w_topfill
)
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
start_arrow(&tpos);
can_cindent = true;
} else {
@@ -9013,7 +9013,7 @@ static int ins_ctrl_ey(int tc)
scrolldown_clamp();
else
scrollup_clamp();
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
} else {
c = ins_copychar(curwin->w_cursor.lnum + (c == Ctrl_Y ? -1 : 1));
if (c != NUL) {
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 3669cbbd2d..41137bf2db 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -3721,8 +3721,8 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
update_topline();
validate_cursor();
update_screen(SOME_VALID);
- highlight_match = FALSE;
- redraw_later(SOME_VALID);
+ highlight_match = false;
+ redraw_later(curwin, SOME_VALID);
curwin->w_p_fen = save_p_fen;
if (msg_row == Rows - 1)
@@ -5751,7 +5751,7 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr,
}
xfree(str);
- redraw_later(SOME_VALID);
+ redraw_later(curwin, SOME_VALID);
win_enter(save_curwin, false); // Return to original window
update_topline();
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 503fd8e0d0..713d18b44d 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -2363,7 +2363,7 @@ void ex_compiler(exarg_T *eap)
do_unlet(S_LEN("b:current_compiler"), true);
snprintf((char *)buf, bufsize, "compiler/%s.vim", eap->arg);
- if (source_runtime(buf, DIP_ALL) == FAIL) {
+ if (source_in_path(p_rtp, buf, DIP_ALL) == FAIL) {
EMSG2(_("E666: compiler not supported: %s"), eap->arg);
}
xfree(buf);
@@ -2581,6 +2581,7 @@ int do_in_runtimepath(char_u *name, int flags, DoInRuntimepathCB callback,
/// return FAIL when no file could be sourced, OK otherwise.
int source_runtime(char_u *name, int flags)
{
+ flags |= (flags & DIP_NORTP) ? 0 : DIP_START;
return source_in_path(p_rtp, name, flags);
}
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 211791c19d..d7ed2fe97d 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -1251,7 +1251,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
char_u *errormsg = NULL; // error message
char_u *after_modifier = NULL;
exarg_T ea;
- int save_msg_scroll = msg_scroll;
+ const int save_msg_scroll = msg_scroll;
cmdmod_T save_cmdmod;
const int save_reg_executing = reg_executing;
char_u *cmd;
@@ -2003,34 +2003,10 @@ doend:
? cmdnames[(int)ea.cmdidx].cmd_name
: (char_u *)NULL);
- if (ea.verbose_save >= 0) {
- p_verbose = ea.verbose_save;
- }
- free_cmdmod();
-
+ undo_cmdmod(&ea, save_msg_scroll);
cmdmod = save_cmdmod;
reg_executing = save_reg_executing;
- if (ea.save_msg_silent != -1) {
- // messages could be enabled for a serious error, need to check if the
- // counters don't become negative
- if (!did_emsg || msg_silent > ea.save_msg_silent) {
- msg_silent = ea.save_msg_silent;
- }
- emsg_silent -= ea.did_esilent;
- if (emsg_silent < 0) {
- emsg_silent = 0;
- }
- // Restore msg_scroll, it's set by file I/O commands, even when no
- // message is actually displayed.
- msg_scroll = save_msg_scroll;
-
- /* "silent reg" or "silent echo x" inside "redir" leaves msg_col
- * somewhere in the line. Put it back in the first column. */
- if (redirecting())
- msg_col = 0;
- }
-
if (ea.did_sandbox) {
sandbox--;
}
@@ -2298,9 +2274,14 @@ int parse_command_modifiers(exarg_T *eap, char_u **errormsg, bool skip_only)
return OK;
}
-// Free contents of "cmdmod".
-static void free_cmdmod(void)
+// Undo and free contents of "cmdmod".
+static void undo_cmdmod(const exarg_T *eap, int save_msg_scroll)
+ FUNC_ATTR_NONNULL_ALL
{
+ if (eap->verbose_save >= 0) {
+ p_verbose = eap->verbose_save;
+ }
+
if (cmdmod.save_ei != NULL) {
/* Restore 'eventignore' to the value before ":noautocmd". */
set_string_option_direct((char_u *)"ei", -1, cmdmod.save_ei,
@@ -2308,8 +2289,27 @@ static void free_cmdmod(void)
free_string_option(cmdmod.save_ei);
}
- if (cmdmod.filter_regmatch.regprog != NULL) {
- vim_regfree(cmdmod.filter_regmatch.regprog);
+ vim_regfree(cmdmod.filter_regmatch.regprog);
+
+ if (eap->save_msg_silent != -1) {
+ // messages could be enabled for a serious error, need to check if the
+ // counters don't become negative
+ if (!did_emsg || msg_silent > eap->save_msg_silent) {
+ msg_silent = eap->save_msg_silent;
+ }
+ emsg_silent -= eap->did_esilent;
+ if (emsg_silent < 0) {
+ emsg_silent = 0;
+ }
+ // Restore msg_scroll, it's set by file I/O commands, even when no
+ // message is actually displayed.
+ msg_scroll = save_msg_scroll;
+
+ // "silent reg" or "silent echo x" inside "redir" leaves msg_col
+ // somewhere in the line. Put it back in the first column.
+ if (redirecting()) {
+ msg_col = 0;
+ }
}
}
@@ -4446,6 +4446,9 @@ void separate_nextcmd(exarg_T *eap)
else if (p[0] == '`' && p[1] == '=' && (eap->argt & XFILE)) {
p += 2;
(void)skip_expr(&p);
+ if (*p == NUL) { // stop at NUL after CTRL-V
+ break;
+ }
}
/* Check for '"': start of comment or '|': next command */
/* :@" does not start a comment!
@@ -7379,7 +7382,7 @@ static void ex_syncbind(exarg_T *eap)
else
scrolldown(-y, TRUE);
curwin->w_scbind_pos = topline;
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
cursor_correct();
curwin->w_redr_status = TRUE;
}
@@ -8504,7 +8507,7 @@ static void ex_pedit(exarg_T *eap)
if (curwin != curwin_save && win_valid(curwin_save)) {
// Return cursor to where we were
validate_cursor();
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
win_enter(curwin_save, true);
}
g_do_tagpreview = 0;
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index d67e9b2d7e..53feffd2d7 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -6483,7 +6483,7 @@ static int open_cmdwin(void)
ccline.redraw_state = kCmdRedrawNone;
ui_call_cmdline_hide(ccline.level);
}
- redraw_later(SOME_VALID);
+ redraw_later(curwin, SOME_VALID);
// Save the command line info, can be used recursively.
save_cmdline(&save_ccline);
diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c
index 6b00b986dc..42a9ef08f9 100644
--- a/src/nvim/ex_session.c
+++ b/src/nvim/ex_session.c
@@ -897,8 +897,8 @@ void ex_mkrc(exarg_T *eap)
if (!failed && view_session) {
if (put_line(fd,
- "let s:so_save = &so | let s:siso_save = &siso"
- " | set so=0 siso=0") == FAIL) {
+ "let s:so_save = &g:so | let s:siso_save = &g:siso"
+ " | setg so=0 siso=0 | setl so=-1 siso=-1") == FAIL) {
failed = true;
}
if (eap->cmdidx == CMD_mksession) {
@@ -949,7 +949,7 @@ void ex_mkrc(exarg_T *eap)
}
if (fprintf(fd,
"%s",
- "let &so = s:so_save | let &siso = s:siso_save\n"
+ "let &g:so = s:so_save | let &g:siso = s:siso_save\n"
"doautoall SessionLoadPost\n")
< 0) {
failed = true;
diff --git a/src/nvim/extmark_defs.h b/src/nvim/extmark_defs.h
index f5ca0ebbb0..382aaf6ed3 100644
--- a/src/nvim/extmark_defs.h
+++ b/src/nvim/extmark_defs.h
@@ -50,10 +50,13 @@ typedef struct {
LuaRef redraw_win;
LuaRef redraw_line;
LuaRef redraw_end;
+ LuaRef hl_def;
+ int hl_valid;
} DecorationProvider;
#define DECORATION_PROVIDER_INIT(ns_id) (DecorationProvider) \
{ ns_id, false, LUA_NOREF, LUA_NOREF, \
- LUA_NOREF, LUA_NOREF, LUA_NOREF }
+ LUA_NOREF, LUA_NOREF, LUA_NOREF, \
+ LUA_NOREF, -1 }
#endif // NVIM_EXTMARK_DEFS_H
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 197aedabec..57001f77ed 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -862,7 +862,7 @@ void foldUpdateAfterInsert(void)
void foldUpdateAll(win_T *win)
{
win->w_foldinvalid = true;
- redraw_win_later(win, NOT_VALID);
+ redraw_later(win, NOT_VALID);
}
// foldMoveTo() {{{2
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 2db8689a56..31dd3fc848 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -92,6 +92,10 @@ EXTERN struct nvim_stats_s {
EXTERN int Rows INIT(= DFLT_ROWS); // nr of rows in the screen
EXTERN int Columns INIT(= DFLT_COLS); // nr of columns in the screen
+EXTERN NS ns_hl_active INIT(= 0); // current ns that defines highlights
+EXTERN bool ns_hl_changed INIT(= false); // highlight need update
+
+
// We use 64-bit file functions here, if available. E.g. ftello() returns
// off_t instead of long, which helps if long is 32 bit and off_t is 64 bit.
// We assume that when fseeko() is available then ftello() is too.
@@ -941,8 +945,10 @@ EXTERN char_u e_readonly[] INIT(= N_(
EXTERN char_u e_readonlyvar[] INIT(= N_(
"E46: Cannot change read-only variable \"%.*s\""));
EXTERN char_u e_dictreq[] INIT(= N_("E715: Dictionary required"));
-EXTERN char_u e_toomanyarg[] INIT(= N_("E118: Too many arguments for function: %s"));
-EXTERN char_u e_dictkey[] INIT(= N_("E716: Key not present in Dictionary: %s"));
+EXTERN char_u e_toomanyarg[] INIT(= N_(
+ "E118: Too many arguments for function: %s"));
+EXTERN char_u e_dictkey[] INIT(= N_(
+ "E716: Key not present in Dictionary: \"%s\""));
EXTERN char_u e_listreq[] INIT(= N_("E714: List required"));
EXTERN char_u e_listdictarg[] INIT(= N_(
"E712: Argument of %s must be a List or Dictionary"));
diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c
index 262afba07a..8403615166 100644
--- a/src/nvim/highlight.c
+++ b/src/nvim/highlight.c
@@ -14,6 +14,7 @@
#include "nvim/ui.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
+#include "nvim/lua/executor.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "highlight.c.generated.h"
@@ -28,12 +29,16 @@ static Map(int, int) *combine_attr_entries;
static Map(int, int) *blend_attr_entries;
static Map(int, int) *blendthrough_attr_entries;
+/// highlight entries private to a namespace
+static Map(ColorKey, ColorItem) *ns_hl;
+
void highlight_init(void)
{
attr_entry_ids = map_new(HlEntry, int)();
combine_attr_entries = map_new(int, int)();
blend_attr_entries = map_new(int, int)();
blendthrough_attr_entries = map_new(int, int)();
+ ns_hl = map_new(ColorKey, ColorItem)();
// index 0 is no attribute, add dummy entry:
kv_push(attr_entries, ((HlEntry){ .attr = HLATTRS_INIT, .kind = kHlUnknown,
@@ -129,21 +134,114 @@ void ui_send_all_hls(UI *ui)
}
/// Get attribute code for a syntax group.
-int hl_get_syn_attr(int idx, HlAttrs at_en)
+int hl_get_syn_attr(int ns_id, int idx, HlAttrs at_en)
{
// TODO(bfredl): should we do this unconditionally
if (at_en.cterm_fg_color != 0 || at_en.cterm_bg_color != 0
|| at_en.rgb_fg_color != -1 || at_en.rgb_bg_color != -1
|| at_en.rgb_sp_color != -1 || at_en.cterm_ae_attr != 0
- || at_en.rgb_ae_attr != 0) {
+ || at_en.rgb_ae_attr != 0 || ns_id != 0) {
return get_attr_entry((HlEntry){ .attr = at_en, .kind = kHlSyntax,
- .id1 = idx, .id2 = 0 });
+ .id1 = idx, .id2 = ns_id });
} else {
// If all the fields are cleared, clear the attr field back to default value
return 0;
}
}
+static ColorKey colored_key(NS ns_id, int syn_id)
+{
+ return (ColorKey){ .ns_id = (int)ns_id, .syn_id = syn_id };
+}
+
+void ns_hl_def(NS ns_id, int hl_id, HlAttrs attrs, int link_id)
+{
+ DecorationProvider *p = get_provider(ns_id, true);
+ int attr_id = link_id > 0 ? -1 : hl_get_syn_attr(ns_id, hl_id, attrs);
+ ColorItem it = { .attr_id = attr_id,
+ .link_id = link_id,
+ .version = p->hl_valid };
+ map_put(ColorKey, ColorItem)(ns_hl, colored_key(ns_id, hl_id), it);
+}
+
+int ns_get_hl(NS ns_id, int hl_id, bool link)
+{
+ static int recursive = 0;
+
+ if (ns_id < 0) {
+ if (ns_hl_active <= 0) {
+ return -1;
+ }
+ ns_id = ns_hl_active;
+ }
+
+ DecorationProvider *p = get_provider(ns_id, true);
+ ColorItem it = map_get(ColorKey, ColorItem)(ns_hl, colored_key(ns_id, hl_id));
+ // TODO(bfredl): map_ref true even this?
+ bool valid_cache = it.version >= p->hl_valid;
+
+ if (!valid_cache && p->hl_def != LUA_NOREF && !recursive) {
+ FIXED_TEMP_ARRAY(args, 3);
+ args.items[0] = INTEGER_OBJ((Integer)ns_id);
+ args.items[1] = STRING_OBJ(cstr_to_string((char *)syn_id2name(hl_id)));
+ args.items[2] = BOOLEAN_OBJ(link);
+ // TODO(bfredl): preload the "global" attr dict?
+
+ Error err = ERROR_INIT;
+ recursive++;
+ Object ret = nlua_call_ref(p->hl_def, "hl_def", args, true, &err);
+ recursive--;
+
+ // TODO(bfredl): or "inherit", combine with global value?
+ bool fallback = true;
+ int tmp = false;
+ HlAttrs attrs = HLATTRS_INIT;
+ if (ret.type == kObjectTypeDictionary) {
+ Dictionary dict = ret.data.dictionary;
+ fallback = false;
+ attrs = dict2hlattrs(dict, true, &it.link_id, &err);
+ for (size_t i = 0; i < dict.size; i++) {
+ char *key = dict.items[i].key.data;
+ Object val = dict.items[i].value;
+ bool truthy = api_object_to_bool(val, key, false, &err);
+
+ if (strequal(key, "fallback")) {
+ fallback = truthy;
+ } else if (strequal(key, "temp")) {
+ tmp = truthy;
+ }
+ }
+ if (it.link_id >= 0) {
+ fallback = true;
+ }
+ }
+
+ it.attr_id = fallback ? -1 : hl_get_syn_attr((int)ns_id, hl_id, attrs);
+ it.version = p->hl_valid-tmp;
+ map_put(ColorKey, ColorItem)(ns_hl, colored_key(ns_id, hl_id), it);
+ }
+
+ if (link) {
+ return it.attr_id >= 0 ? -1 : it.link_id;
+ } else {
+ return it.attr_id;
+ }
+}
+
+
+bool win_check_ns_hl(win_T *wp)
+{
+ if (ns_hl_changed) {
+ highlight_changed();
+ if (wp) {
+ update_window_hl(wp, true);
+ }
+ ns_hl_changed = false;
+ return true;
+ }
+ return false;
+}
+
/// Get attribute code for a builtin highlight group.
///
/// The final syntax group could be modified by hi-link or 'winhighlight'.
@@ -204,6 +302,17 @@ void update_window_hl(win_T *wp, bool invalid)
wp->w_hl_attr_normal = float_win ? HL_ATTR(HLF_NFLOAT) : 0;
}
+ // NOOOO! You cannot just pretend that "Normal" is just like any other
+ // syntax group! It needs at least 10 layers of special casing! Noooooo!
+ //
+ // haha, theme engine go brrr
+ int normality = syn_check_group((const char_u *)S_LEN("Normal"));
+ int ns_attr = ns_get_hl(-1, normality, false);
+ if (ns_attr > 0) {
+ // TODO(bfredl): hantera NormalNC and so on
+ wp->w_hl_attr_normal = ns_attr;
+ }
+
// if blend= attribute is not set, 'winblend' value overrides it.
if (wp->w_floating && wp->w_p_winbl > 0) {
HlEntry entry = kv_A(attr_entries, wp->w_hl_attr_normal);
@@ -275,6 +384,7 @@ void clear_hl_tables(bool reinit)
map_free(int, int)(combine_attr_entries);
map_free(int, int)(blend_attr_entries);
map_free(int, int)(blendthrough_attr_entries);
+ map_free(ColorKey, ColorItem)(ns_hl);
}
}
@@ -663,6 +773,103 @@ Dictionary hlattrs2dict(HlAttrs ae, bool use_rgb)
return hl;
}
+HlAttrs dict2hlattrs(Dictionary dict, bool use_rgb, int *link_id, Error *err)
+{
+ HlAttrs hlattrs = HLATTRS_INIT;
+
+ int32_t fg = -1, bg = -1, sp = -1;
+ int16_t mask = 0;
+ for (size_t i = 0; i < dict.size; i++) {
+ char *key = dict.items[i].key.data;
+ Object val = dict.items[i].value;
+
+ struct {
+ const char *name;
+ int16_t flag;
+ } flags[] = {
+ { "bold", HL_BOLD },
+ { "standout", HL_STANDOUT },
+ { "underline", HL_UNDERLINE },
+ { "undercurl", HL_UNDERCURL },
+ { "italic", HL_ITALIC },
+ { "reverse", HL_INVERSE },
+ { NULL, 0 },
+ };
+
+ int j;
+ for (j = 0; flags[j].name; j++) {
+ if (strequal(flags[j].name, key)) {
+ if (api_object_to_bool(val, key, false, err)) {
+ mask = mask | flags[j].flag;
+ }
+ break;
+ }
+ }
+
+ struct {
+ const char *name;
+ const char *shortname;
+ int *dest;
+ } colors[] = {
+ { "foreground", "fg", &fg },
+ { "background", "bg", &bg },
+ { "special", "sp", &sp },
+ { NULL, NULL, NULL },
+ };
+
+ int k;
+ for (k = 0; (!flags[j].name) && colors[k].name; k++) {
+ if (strequal(colors[k].name, key) || strequal(colors[k].shortname, key)) {
+ if (val.type == kObjectTypeInteger) {
+ *colors[k].dest = (int)val.data.integer;
+ } else if (val.type == kObjectTypeString) {
+ String str = val.data.string;
+ // TODO(bfredl): be more fancy with "bg", "fg" etc
+ if (str.size) {
+ *colors[k].dest = name_to_color(str.data);
+ }
+ } else {
+ api_set_error(err, kErrorTypeValidation,
+ "'%s' must be string or integer", key);
+ }
+ break;
+ }
+ }
+
+
+ if (flags[j].name || colors[k].name) {
+ // handled above
+ } else if (link_id && strequal(key, "link")) {
+ if (val.type == kObjectTypeString) {
+ String str = val.data.string;
+ *link_id = syn_check_group((const char_u *)str.data, (int)str.size);
+ } else if (val.type == kObjectTypeInteger) {
+ // TODO(bfredl): validate range?
+ *link_id = (int)val.data.integer;
+ } else {
+ api_set_error(err, kErrorTypeValidation,
+ "'link' must be string or integer");
+ }
+ }
+
+ if (ERROR_SET(err)) {
+ return hlattrs; // error set, caller should not use retval
+ }
+ }
+
+ if (use_rgb) {
+ hlattrs.rgb_ae_attr = mask;
+ hlattrs.rgb_bg_color = bg;
+ hlattrs.rgb_fg_color = fg;
+ hlattrs.rgb_sp_color = sp;
+ } else {
+ hlattrs.cterm_ae_attr = mask;
+ hlattrs.cterm_bg_color = bg == -1 ? cterm_normal_bg_color : bg + 1;
+ hlattrs.cterm_fg_color = fg == -1 ? cterm_normal_fg_color : fg + 1;
+ }
+
+ return hlattrs;
+}
Array hl_inspect(int attr)
{
Array ret = ARRAY_DICT_INIT;
diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h
index 36f3181674..6a5c593ab1 100644
--- a/src/nvim/highlight_defs.h
+++ b/src/nvim/highlight_defs.h
@@ -4,6 +4,7 @@
#include <inttypes.h>
#include "nvim/macros.h"
+#include "nvim/types.h"
typedef int32_t RgbValue;
@@ -180,6 +181,20 @@ typedef struct {
HlKind kind;
int id1;
int id2;
+ int winid;
} HlEntry;
+typedef struct {
+ int ns_id;
+ int syn_id;
+} ColorKey;
+
+typedef struct {
+ int attr_id;
+ int link_id;
+ int version;
+} ColorItem;
+#define COLOR_ITEM_INITIALIZER { .attr_id = -1, .link_id = -1, .version = -1 }
+
+
#endif // NVIM_HIGHLIGHT_DEFS_H
diff --git a/src/nvim/indent.c b/src/nvim/indent.c
index bb0fdfec01..9e6693afdf 100644
--- a/src/nvim/indent.c
+++ b/src/nvim/indent.c
@@ -295,13 +295,17 @@ int set_indent(int size, int flags)
// Replace the line (unless undo fails).
if (!(flags & SIN_UNDO) || (u_savesub(curwin->w_cursor.lnum) == OK)) {
+ const colnr_T old_offset = (colnr_T)(p - oldline);
+ const colnr_T new_offset = (colnr_T)(s - newline);
+
+ // this may free "newline"
ml_replace(curwin->w_cursor.lnum, newline, false);
if (!(flags & SIN_NOMARK)) {
extmark_splice_cols(curbuf,
(int)curwin->w_cursor.lnum-1,
skipcols,
- (int)(p-oldline) - skipcols,
- (int)(s-newline) - skipcols,
+ old_offset - skipcols,
+ new_offset - skipcols,
kExtmarkUndo);
}
@@ -311,15 +315,14 @@ int set_indent(int size, int flags)
// Correct saved cursor position if it is in this line.
if (saved_cursor.lnum == curwin->w_cursor.lnum) {
- if (saved_cursor.col >= (colnr_T)(p - oldline)) {
+ if (saved_cursor.col >= old_offset) {
// Cursor was after the indent, adjust for the number of
// bytes added/removed.
- saved_cursor.col += ind_len - (colnr_T)(p - oldline);
-
- } else if (saved_cursor.col >= (colnr_T)(s - newline)) {
+ saved_cursor.col += ind_len - old_offset;
+ } else if (saved_cursor.col >= new_offset) {
// Cursor was in the indent, and is now after it, put it back
// at the start of the indent (replacing spaces with TAB).
- saved_cursor.col = (colnr_T)(s - newline);
+ saved_cursor.col = new_offset;
}
}
retval = true;
diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c
index bb443161ef..9298e57411 100644
--- a/src/nvim/indent_c.c
+++ b/src/nvim/indent_c.c
@@ -1676,6 +1676,9 @@ void parse_cino(buf_T *buf)
// Handle C++ extern "C" or "C++"
buf->b_ind_cpp_extern_c = 0;
+ // Handle C #pragma directives
+ buf->b_ind_pragma = 0;
+
for (p = buf->b_p_cino; *p; ) {
l = p++;
if (*p == '-') {
@@ -1747,6 +1750,7 @@ void parse_cino(buf_T *buf)
case 'N': buf->b_ind_cpp_namespace = n; break;
case 'k': buf->b_ind_if_for_while = n; break;
case 'E': buf->b_ind_cpp_extern_c = n; break;
+ case 'P': buf->b_ind_pragma = n; break;
}
if (*p == ',')
++p;
@@ -1858,12 +1862,14 @@ int get_c_indent(void)
goto laterend;
}
- /*
- * #defines and so on always go at the left when included in 'cinkeys'.
- */
+ // #defines and so on go at the left when included in 'cinkeys',
+ // exluding pragmas when customized in 'cinoptions'
if (*theline == '#' && (*linecopy == '#' || in_cinkeys('#', ' ', true))) {
- amount = curbuf->b_ind_hash_comment;
- goto theend;
+ const char_u *const directive = skipwhite(theline + 1);
+ if (curbuf->b_ind_pragma == 0 || STRNCMP(directive, "pragma", 6) != 0) {
+ amount = curbuf->b_ind_hash_comment;
+ goto theend;
+ }
}
/*
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 5c665920b5..a095f298f2 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -549,14 +549,6 @@ static lua_State *nlua_enter(void)
// stack: (empty)
lua_getglobal(lstate, "vim");
// stack: vim
- lua_getfield(lstate, -1, "_update_package_paths");
- // stack: vim, vim._update_package_paths
- if (lua_pcall(lstate, 0, 0, 0)) {
- // stack: vim, error
- nlua_error(lstate, _("E5117: Error while updating package paths: %.*s"));
- // stack: vim
- }
- // stack: vim
lua_pop(lstate, 1);
// stack: (empty)
last_p_rtp = (const void *)p_rtp;
@@ -564,14 +556,6 @@ static lua_State *nlua_enter(void)
return lstate;
}
-/// Force an update of lua's package paths if runtime path has changed.
-bool nlua_update_package_path(void)
-{
- lua_State *const lstate = nlua_enter();
-
- return !!lstate;
-}
-
static void nlua_print_event(void **argv)
{
char *str = argv[0];
@@ -891,6 +875,17 @@ LuaRef nlua_newref(lua_State *lstate, LuaRef original_ref)
return new_ref;
}
+LuaRef api_new_luaref(LuaRef original_ref)
+{
+ if (original_ref == LUA_NOREF) {
+ return LUA_NOREF;
+ }
+
+ lua_State *const lstate = nlua_enter();
+ return nlua_newref(lstate, original_ref);
+}
+
+
/// Evaluate lua string
///
/// Used for luaeval().
diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c
index 5258352e72..c53e208b00 100644
--- a/src/nvim/lua/treesitter.c
+++ b/src/nvim/lua/treesitter.c
@@ -58,6 +58,7 @@ static struct luaL_Reg node_meta[] = {
{ "__tostring", node_tostring },
{ "__eq", node_eq },
{ "__len", node_child_count },
+ { "id", node_id },
{ "range", node_range },
{ "start", node_start },
{ "end_", node_end },
@@ -176,10 +177,11 @@ int tslua_add_language(lua_State *L)
}
uint32_t lang_version = ts_language_version(lang);
- if (lang_version < TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION) {
+ if (lang_version < TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION
+ || lang_version > TREE_SITTER_LANGUAGE_VERSION) {
return luaL_error(
L,
- "ABI version mismatch : expected %" PRIu32 ", found %" PRIu32,
+ "ABI version mismatch : expected %d, found %d",
TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION, lang_version);
}
@@ -246,7 +248,12 @@ int tslua_push_parser(lua_State *L)
}
TSParser *parser = ts_parser_new();
- ts_parser_set_language(parser, lang);
+
+ if (!ts_parser_set_language(parser, lang)) {
+ ts_parser_delete(parser);
+ return luaL_error(L, "Failed to load language : %s", lang_name);
+ }
+
TSLua_parser *p = lua_newuserdata(L, sizeof(TSLua_parser)); // [udata]
p->parser = parser;
p->tree = NULL;
@@ -342,7 +349,7 @@ static int parser_parse(lua_State *L)
return 0;
}
- TSTree *new_tree;
+ TSTree *new_tree = NULL;
size_t len;
const char *str;
long bufnr;
@@ -374,6 +381,12 @@ static int parser_parse(lua_State *L)
return luaL_error(L, "invalid argument to parser:parse()");
}
+ // Sometimes parsing fails (timeout, or wrong parser ABI)
+ // In those case, just return an error.
+ if (!new_tree) {
+ return luaL_error(L, "An error occured when parsing.");
+ }
+
uint32_t n_ranges = 0;
TSRange *changed = p->tree ? ts_tree_get_changed_ranges(p->tree, new_tree,
&n_ranges) : NULL;
@@ -621,6 +634,17 @@ static int node_eq(lua_State *L)
return 1;
}
+static int node_id(lua_State *L)
+{
+ TSNode node;
+ if (!node_check(L, 1, &node)) {
+ return 0;
+ }
+
+ lua_pushlstring(L, (const char *)&node.id, sizeof node.id);
+ return 1;
+}
+
static int node_range(lua_State *L)
{
TSNode node;
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index bfa8b91208..85d39eaef4 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -92,67 +92,48 @@ function vim._os_proc_children(ppid)
return children
end
--- TODO(ZyX-I): Create compatibility layer.
---{{{1 package.path updater function
--- Last inserted paths. Used to clear out items from package.[c]path when they
--- are no longer in &runtimepath.
-local last_nvim_paths = {}
-function vim._update_package_paths()
- local cur_nvim_paths = {}
- local rtps = vim.api.nvim_list_runtime_paths()
- local sep = package.config:sub(1, 1)
- for _, key in ipairs({'path', 'cpath'}) do
- local orig_str = package[key] .. ';'
- local pathtrails_ordered = {}
- local orig = {}
- -- Note: ignores trailing item without trailing `;`. Not using something
- -- simpler in order to preserve empty items (stand for default path).
- for s in orig_str:gmatch('[^;]*;') do
- s = s:sub(1, -2) -- Strip trailing semicolon
- orig[#orig + 1] = s
- end
- if key == 'path' then
- -- /?.lua and /?/init.lua
- pathtrails_ordered = {sep .. '?.lua', sep .. '?' .. sep .. 'init.lua'}
- else
- local pathtrails = {}
- for _, s in ipairs(orig) do
- -- Find out path patterns. pathtrail should contain something like
- -- /?.so, \?.dll. This allows not to bother determining what correct
- -- suffixes are.
- local pathtrail = s:match('[/\\][^/\\]*%?.*$')
- if pathtrail and not pathtrails[pathtrail] then
- pathtrails[pathtrail] = true
- pathtrails_ordered[#pathtrails_ordered + 1] = pathtrail
- end
- end
- end
- local new = {}
- for _, rtp in ipairs(rtps) do
- if not rtp:match(';') then
- for _, pathtrail in pairs(pathtrails_ordered) do
- local new_path = rtp .. sep .. 'lua' .. pathtrail
- -- Always keep paths from &runtimepath at the start:
- -- append them here disregarding orig possibly containing one of them.
- new[#new + 1] = new_path
- cur_nvim_paths[new_path] = true
- end
- end
+local pathtrails = {}
+vim._so_trails = {}
+for s in (package.cpath..';'):gmatch('[^;]*;') do
+ s = s:sub(1, -2) -- Strip trailing semicolon
+ -- Find out path patterns. pathtrail should contain something like
+ -- /?.so, \?.dll. This allows not to bother determining what correct
+ -- suffixes are.
+ local pathtrail = s:match('[/\\][^/\\]*%?.*$')
+ if pathtrail and not pathtrails[pathtrail] then
+ pathtrails[pathtrail] = true
+ table.insert(vim._so_trails, pathtrail)
+ end
+end
+
+function vim._load_package(name)
+ -- tricky: when debugging this function we must let vim.inspect
+ -- module to be loaded first:
+ --local inspect = (name == "vim.inspect") and tostring or vim.inspect
+
+ local basename = name:gsub('%.', '/')
+ local paths = {"lua/"..basename..".lua", "lua/"..basename.."/init.lua"}
+ for _,path in ipairs(paths) do
+ local found = vim.api.nvim_get_runtime_file(path, false)
+ if #found > 0 then
+ return loadfile(found[1])
end
- for _, orig_path in ipairs(orig) do
- -- Handle removing obsolete paths originating from &runtimepath: such
- -- paths either belong to cur_nvim_paths and were already added above or
- -- to last_nvim_paths and should not be added at all if corresponding
- -- entry was removed from &runtimepath list.
- if not (cur_nvim_paths[orig_path] or last_nvim_paths[orig_path]) then
- new[#new + 1] = orig_path
- end
+ end
+
+ for _,trail in ipairs(vim._so_trails) do
+ local path = "lua/"..trail:gsub('?',basename)
+ local found = vim.api.nvim_get_runtime_file(path, false)
+ if #found > 0 then
+ return package.loadlib(found[1])
end
- package[key] = table.concat(new, ';')
end
- last_nvim_paths = cur_nvim_paths
+ return nil
end
+table.insert(package.loaders, 1, vim._load_package)
+
+-- TODO(ZyX-I): Create compatibility layer.
+
--- Return a human-readable representation of the given object.
---
--@see https://github.com/kikito/inspect.lua
diff --git a/src/nvim/main.c b/src/nvim/main.c
index a22df9cc69..27bf5c45c6 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -446,7 +446,7 @@ int main(int argc, char **argv)
if (exmode_active || use_remote_ui || use_builtin_ui) {
// Don't clear the screen when starting in Ex mode, or when a UI might have
// displayed messages.
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
} else {
screenclear(); // clear screen
TIME_MSG("clearing screen");
diff --git a/src/nvim/map.c b/src/nvim/map.c
index ca8ea76333..7d97b7f13d 100644
--- a/src/nvim/map.c
+++ b/src/nvim/map.c
@@ -12,6 +12,9 @@
#include <stdbool.h>
#include <string.h>
+#include <lua.h>
+#include <lauxlib.h>
+
#include "nvim/map.h"
#include "nvim/map_defs.h"
#include "nvim/vim.h"
@@ -173,6 +176,20 @@ static inline bool HlEntry_eq(HlEntry ae1, HlEntry ae2)
return memcmp(&ae1, &ae2, sizeof(ae1)) == 0;
}
+static inline khint_t ColorKey_hash(ColorKey ae)
+{
+ const uint8_t *data = (const uint8_t *)&ae;
+ khint_t h = 0;
+ for (size_t i = 0; i < sizeof(ae); i++) {
+ h = (h << 5) - h + data[i];
+ }
+ return h;
+}
+
+static inline bool ColorKey_eq(ColorKey ae1, ColorKey ae2)
+{
+ return memcmp(&ae1, &ae2, sizeof(ae1)) == 0;
+}
MAP_IMPL(int, int, DEFAULT_INITIALIZER)
@@ -191,6 +208,7 @@ MAP_IMPL(String, MsgpackRpcRequestHandler, MSGPACK_HANDLER_INITIALIZER)
MAP_IMPL(HlEntry, int, DEFAULT_INITIALIZER)
MAP_IMPL(String, handle_T, 0)
+MAP_IMPL(ColorKey, ColorItem, COLOR_ITEM_INITIALIZER)
/// Deletes a key:value pair from a string:pointer map, and frees the
/// storage of both key and value.
diff --git a/src/nvim/map.h b/src/nvim/map.h
index 63a18f4129..7bd3d31330 100644
--- a/src/nvim/map.h
+++ b/src/nvim/map.h
@@ -55,6 +55,8 @@ MAP_DECLS(String, MsgpackRpcRequestHandler)
MAP_DECLS(HlEntry, int)
MAP_DECLS(String, handle_T)
+MAP_DECLS(ColorKey, ColorItem)
+
#define map_new(T, U) map_##T##_##U##_new
#define map_free(T, U) map_##T##_##U##_free
#define map_get(T, U) map_##T##_##U##_get
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index b060464383..4ba2e36656 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -193,7 +193,7 @@ ex_menu(exarg_T *eap)
vimmenu_T **root_menu_ptr = get_root_menu(menu_path);
if (root_menu_ptr == &curwin->w_winbar) {
// Assume the window toolbar menu will change.
- redraw_later(NOT_VALID);
+ redraw_later(curwin, NOT_VALID);
}
if (enable != kNone) {
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 6cd5616acf..06ba607323 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -1216,7 +1216,7 @@ void wait_return(int redraw)
ui_refresh();
} else if (!skip_redraw) {
if (redraw == true || (msg_scrolled != 0 && redraw != -1)) {
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
}
if (ui_has(kUIMessages)) {
msg_ext_clear(true);
@@ -2222,7 +2222,7 @@ void msg_scroll_up(bool may_throttle)
///
/// Probably message scrollback storage should reimplented as a file_buffer, and
/// message scrolling in TUI be reimplemented as a modal floating window. Then
-/// we get throttling "for free" using standard redraw_win_later code paths.
+/// we get throttling "for free" using standard redraw_later code paths.
void msg_scroll_flush(void)
{
if (msg_grid.throttled) {
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index fcd9ee4f75..d8ff83f479 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -286,7 +286,7 @@ retnomove:
check_topfill(curwin, false);
curwin->w_valid &=
~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
row = 0;
} else if (row >= curwin->w_height_inner) {
count = 0;
@@ -316,7 +316,7 @@ retnomove:
}
}
check_topfill(curwin, false);
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
curwin->w_valid &=
~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
row = curwin->w_height_inner - 1;
diff --git a/src/nvim/move.c b/src/nvim/move.c
index e2a304efa5..98a7792a09 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -107,7 +107,7 @@ void redraw_for_cursorline(win_T *wp)
&& !pum_visible()) {
if (wp->w_p_rnu) {
// win_line() will redraw the number column only.
- redraw_win_later(wp, VALID);
+ redraw_later(wp, VALID);
}
if (win_cursorline_standout(wp)) {
if (wp->w_redr_type <= VALID && wp->w_last_cursorline != 0) {
@@ -117,7 +117,7 @@ void redraw_for_cursorline(win_T *wp)
redrawWinline(wp, wp->w_last_cursorline);
redrawWinline(wp, wp->w_cursor.lnum);
} else {
- redraw_win_later(wp, SOME_VALID);
+ redraw_later(wp, SOME_VALID);
}
}
}
@@ -172,7 +172,7 @@ void update_topline(void)
// If the buffer is empty, always set topline to 1.
if (BUFEMPTY()) { // special case - file is empty
if (curwin->w_topline != 1) {
- redraw_later(NOT_VALID);
+ redraw_later(curwin, NOT_VALID);
}
curwin->w_topline = 1;
curwin->w_botline = 2;
@@ -326,12 +326,14 @@ void update_topline(void)
dollar_vcol = -1;
if (curwin->w_skipcol != 0) {
curwin->w_skipcol = 0;
- redraw_later(NOT_VALID);
- } else
- redraw_later(VALID);
- /* May need to set w_skipcol when cursor in w_topline. */
- if (curwin->w_cursor.lnum == curwin->w_topline)
+ redraw_later(curwin, NOT_VALID);
+ } else {
+ redraw_later(curwin, VALID);
+ }
+ // May need to set w_skipcol when cursor in w_topline.
+ if (curwin->w_cursor.lnum == curwin->w_topline) {
validate_cursor();
+ }
}
*so_ptr = save_so;
@@ -439,7 +441,7 @@ void changed_window_setting_win(win_T *wp)
wp->w_lines_valid = 0;
changed_line_abv_curs_win(wp);
wp->w_valid &= ~(VALID_BOTLINE|VALID_BOTLINE_AP|VALID_TOPLINE);
- redraw_win_later(wp, NOT_VALID);
+ redraw_later(wp, NOT_VALID);
}
/*
@@ -455,8 +457,8 @@ void set_topline(win_T *wp, linenr_T lnum)
wp->w_topline_was_set = true;
wp->w_topfill = 0;
wp->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_TOPLINE);
- /* Don't set VALID_TOPLINE here, 'scrolloff' needs to be checked. */
- redraw_later(VALID);
+ // Don't set VALID_TOPLINE here, 'scrolloff' needs to be checked.
+ redraw_later(wp, VALID);
}
/*
@@ -634,7 +636,7 @@ void validate_virtcol_win(win_T *wp)
if (wp->w_p_cuc
&& !pum_visible()
)
- redraw_win_later(wp, SOME_VALID);
+ redraw_later(wp, SOME_VALID);
}
}
@@ -830,7 +832,7 @@ void curs_columns(
curwin->w_leftcol = new_leftcol;
win_check_anchored_floats(curwin);
// screen has to be redrawn with new curwin->w_leftcol
- redraw_later(NOT_VALID);
+ redraw_later(curwin, NOT_VALID);
}
}
curwin->w_wcol -= curwin->w_leftcol;
@@ -934,13 +936,14 @@ void curs_columns(
} else {
curwin->w_skipcol = 0;
}
- if (prev_skipcol != curwin->w_skipcol)
- redraw_later(NOT_VALID);
+ if (prev_skipcol != curwin->w_skipcol) {
+ redraw_later(curwin, NOT_VALID);
+ }
/* Redraw when w_virtcol changes and 'cursorcolumn' is set */
if (curwin->w_p_cuc && (curwin->w_valid & VALID_VIRTCOL) == 0
&& !pum_visible()) {
- redraw_later(SOME_VALID);
+ redraw_later(curwin, SOME_VALID);
}
// now w_leftcol is valid, avoid check_cursor_moved() thinking otherwise
@@ -2013,7 +2016,7 @@ int onepage(Direction dir, long count)
}
}
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
return retval;
}
@@ -2199,7 +2202,7 @@ void halfpage(bool flag, linenr_T Prenum)
check_topfill(curwin, !flag);
cursor_correct();
beginline(BL_SOL | BL_FIX);
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
}
void do_check_cursorbind(void)
@@ -2247,7 +2250,7 @@ void do_check_cursorbind(void)
}
// Correct cursor for multi-byte character.
mb_adjust_cursor();
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
// Only scroll when 'scrollbind' hasn't done this.
if (!curwin->w_p_scb) {
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 92ca29209e..68ef4cd41e 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -262,11 +262,9 @@ static void parse_msgpack(Channel *channel)
call_set_error(channel, buf, ERROR_LOG_LEVEL);
}
msgpack_unpacked_destroy(&unpacked);
- // Bail out from this event loop iteration
- return;
+ } else {
+ handle_request(channel, &unpacked.data);
}
-
- handle_request(channel, &unpacked.data);
}
if (result == MSGPACK_UNPACK_NOMEM_ERROR) {
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 1cc400166c..11e8d354e4 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -903,6 +903,10 @@ normal_end:
msg_nowait = false;
+ if (finish_op) {
+ set_reg_var(get_default_register_name());
+ }
+
// Reset finish_op, in case it was set
s->c = finish_op;
finish_op = false;
@@ -3601,7 +3605,7 @@ void check_scrollbind(linenr_T topline_diff, long leftcol_diff)
scrolldown(-y, false);
}
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
cursor_correct();
curwin->w_redr_status = true;
}
@@ -4143,7 +4147,7 @@ void scroll_redraw(int up, long count)
if (curwin->w_cursor.lnum != prev_lnum)
coladvance(curwin->w_curswant);
curwin->w_viewport_invalid = true;
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
}
/*
@@ -4241,7 +4245,7 @@ dozet:
FALLTHROUGH;
case 't': scroll_cursor_top(0, true);
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
set_fraction(curwin);
break;
@@ -4250,7 +4254,7 @@ dozet:
FALLTHROUGH;
case 'z': scroll_cursor_halfway(true);
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
set_fraction(curwin);
break;
@@ -4271,7 +4275,7 @@ dozet:
FALLTHROUGH;
case 'b': scroll_cursor_bot(0, true);
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
set_fraction(curwin);
break;
@@ -4318,7 +4322,7 @@ dozet:
col = 0;
if (curwin->w_leftcol != col) {
curwin->w_leftcol = col;
- redraw_later(NOT_VALID);
+ redraw_later(curwin, NOT_VALID);
}
}
break;
@@ -4337,7 +4341,7 @@ dozet:
}
if (curwin->w_leftcol != col) {
curwin->w_leftcol = col;
- redraw_later(NOT_VALID);
+ redraw_later(curwin, NOT_VALID);
}
}
break;
@@ -4690,7 +4694,7 @@ static void nv_clear(cmdarg_T *cap)
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
wp->w_s->b_syn_slow = false;
}
- redraw_later(CLEAR);
+ redraw_later(curwin, CLEAR);
}
}
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 939cde0ba1..9e7d81fc82 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -2652,7 +2652,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
xfree(reg->y_array);
}
if (curwin->w_p_rnu) {
- redraw_later(SOME_VALID); // cursor moved to start
+ redraw_later(curwin, SOME_VALID); // cursor moved to start
}
if (message) { // Display message about yank?
if (yank_type == kMTCharWise && yanklines == 1) {
diff --git a/src/nvim/option.c b/src/nvim/option.c
index ca902d5669..fcc051ef1a 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -2566,7 +2566,7 @@ static bool valid_spellfile(const char_u *val)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
for (const char_u *s = val; *s != NUL; s++) {
- if (!vim_isfilec(*s) && *s != ',') {
+ if (!vim_isfilec(*s) && *s != ',' && *s != ' ') {
return false;
}
}
@@ -3121,7 +3121,7 @@ ambw_end:
} else {
if (curwin->w_status_height) {
curwin->w_redr_status = true;
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
}
curbuf->b_help = (curbuf->b_p_bt[0] == 'h');
redraw_titles();
@@ -3364,10 +3364,6 @@ ambw_end:
if (!parse_winhl_opt(curwin)) {
errmsg = e_invarg;
}
- } else if (varp == &p_rtp) { // 'runtimepath'
- if (!nlua_update_package_path()) {
- errmsg = (char_u *)N_("E970: Failed to initialize lua interpreter");
- }
} else {
// Options that are a list of flags.
p = NULL;
@@ -3751,11 +3747,10 @@ static char_u *set_chars_option(win_T *wp, char_u **varp, bool set)
/// Return error message or NULL.
char_u *check_stl_option(char_u *s)
{
- int itemcnt = 0;
int groupdepth = 0;
static char_u errbuf[80];
- while (*s && itemcnt < STL_MAX_ITEM) {
+ while (*s) {
// Check for valid keys after % sequences
while (*s && *s != '%') {
s++;
@@ -3764,9 +3759,6 @@ char_u *check_stl_option(char_u *s)
break;
}
s++;
- if (*s != '%' && *s != ')') {
- itemcnt++;
- }
if (*s == '%' || *s == STL_TRUNCMARK || *s == STL_SEPARATE) {
s++;
continue;
@@ -3808,9 +3800,6 @@ char_u *check_stl_option(char_u *s)
}
}
}
- if (itemcnt >= STL_MAX_ITEM) {
- return (char_u *)N_("E541: too many items");
- }
if (groupdepth != 0) {
return (char_u *)N_("E542: unbalanced groups");
}
@@ -4702,7 +4691,7 @@ static void check_redraw(uint32_t flags)
redraw_curbuf_later(NOT_VALID);
}
if (flags & P_RWINONLY) {
- redraw_later(NOT_VALID);
+ redraw_later(curwin, NOT_VALID);
}
if (doclear) {
redraw_all_later(CLEAR);
@@ -5716,12 +5705,12 @@ void unset_global_local_option(char *name, void *from)
case PV_LCS:
clear_string_option(&((win_T *)from)->w_p_lcs);
set_chars_option((win_T *)from, &((win_T *)from)->w_p_lcs, true);
- redraw_win_later((win_T *)from, NOT_VALID);
+ redraw_later((win_T *)from, NOT_VALID);
break;
case PV_FCS:
clear_string_option(&((win_T *)from)->w_p_fcs);
set_chars_option((win_T *)from, &((win_T *)from)->w_p_fcs, true);
- redraw_win_later((win_T *)from, NOT_VALID);
+ redraw_later((win_T *)from, NOT_VALID);
break;
}
}
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 4042b79262..af0ea7f4a2 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -188,6 +188,7 @@ enum {
#define GO_ASELML 'A' // autoselect modeless selection
#define GO_BOT 'b' // use bottom scrollbar
#define GO_CONDIALOG 'c' // use console dialog
+#define GO_DARKTHEME 'd' // use dark theme variant
#define GO_TABLINE 'e' // may show tabline
#define GO_FORG 'f' // start GUI in foreground
#define GO_GREY 'g' // use grey menu items
@@ -205,7 +206,7 @@ enum {
#define GO_FOOTER 'F' // add footer
#define GO_VERTICAL 'v' // arrange dialog buttons vertically
#define GO_KEEPWINSIZE 'k' // keep GUI window size
-#define GO_ALL "aAbcefFghilmMprTvk" // all possible flags for 'go'
+#define GO_ALL "aAbcdefFghilmMprTvk" // all possible flags for 'go'
// flags for 'comments' option
#define COM_NEST 'n' // comments strings nest
diff --git a/src/nvim/os/os_defs.h b/src/nvim/os/os_defs.h
index c8ac4218f6..bd5f2b889d 100644
--- a/src/nvim/os/os_defs.h
+++ b/src/nvim/os/os_defs.h
@@ -16,10 +16,11 @@
#define BASENAMELEN (NAME_MAX - 5)
// Use the system path length if it makes sense.
-#if defined(PATH_MAX) && (PATH_MAX > 1024)
+# define DEFAULT_MAXPATHL 4096
+#if defined(PATH_MAX) && (PATH_MAX > DEFAULT_MAXPATHL)
# define MAXPATHL PATH_MAX
#else
-# define MAXPATHL 1024
+# define MAXPATHL DEFAULT_MAXPATHL
#endif
// Command-processing buffer. Use large buffers for all platforms.
diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c
index d2d20852aa..ac0c1f6eb1 100644
--- a/src/nvim/popupmnu.c
+++ b/src/nvim/popupmnu.c
@@ -786,7 +786,7 @@ static int pum_set_selected(int n, int repeat)
// Return cursor to where we were
validate_cursor();
- redraw_later(SOME_VALID);
+ redraw_later(curwin, SOME_VALID);
// When the preview window was resized we need to
// update the view on the buffer. Only go back to
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 1cd7879dc0..6ca97c3072 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -3707,7 +3707,7 @@ static void qf_win_goto(win_T *win, linenr_T lnum)
curwin->w_cursor.coladd = 0;
curwin->w_curswant = 0;
update_topline(); // scroll to show the line
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
curwin->w_redr_status = true; // update ruler
curwin = old_curwin;
curbuf = curwin->w_buffer;
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index df0c5ce791..36a6ae59f8 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -25,7 +25,7 @@
//
// Commands that scroll a window change w_topline and must call
// check_cursor() to move the cursor into the visible part of the window, and
-// call redraw_later(VALID) to have the window displayed by update_screen()
+// call redraw_later(wp, VALID) to have the window displayed by update_screen()
// later.
//
// Commands that change text in the buffer must call changed_bytes() or
@@ -37,7 +37,7 @@
//
// Commands that change how a window is displayed (e.g., setting 'list') or
// invalidate the contents of a window in another way (e.g., change fold
-// settings), must call redraw_later(NOT_VALID) to have the whole window
+// settings), must call redraw_later(wp, NOT_VALID) to have the whole window
// redisplayed by update_screen() later.
//
// Commands that change how a buffer is displayed (e.g., setting 'tabstop')
@@ -45,11 +45,11 @@
// buffer redisplayed by update_screen() later.
//
// Commands that change highlighting and possibly cause a scroll too must call
-// redraw_later(SOME_VALID) to update the whole window but still use scrolling
-// to avoid redrawing everything. But the length of displayed lines must not
-// change, use NOT_VALID then.
+// redraw_later(wp, SOME_VALID) to update the whole window but still use
+// scrolling to avoid redrawing everything. But the length of displayed lines
+// must not change, use NOT_VALID then.
//
-// Commands that move the window position must call redraw_later(NOT_VALID).
+// Commands that move the window position must call redraw_later(wp, NOT_VALID).
// TODO(neovim): should minimize redrawing by scrolling when possible.
//
// Commands that change everything (e.g., resizing the screen) must call
@@ -176,7 +176,7 @@ static bool provider_invoke(NS ns_id, const char *name, LuaRef ref,
textlock--;
if (!ERROR_SET(&err)
- && api_coerce_to_bool(ret, "provider %s retval", default_true, &err)) {
+ && api_object_to_bool(ret, "provider %s retval", default_true, &err)) {
return true;
}
@@ -195,17 +195,11 @@ static bool provider_invoke(NS ns_id, const char *name, LuaRef ref,
return false;
}
-/*
- * Redraw the current window later, with update_screen(type).
- * Set must_redraw only if not already set to a higher value.
- * e.g. if must_redraw is CLEAR, type NOT_VALID will do nothing.
- */
-void redraw_later(int type)
-{
- redraw_win_later(curwin, type);
-}
-
-void redraw_win_later(win_T *wp, int type)
+/// Redraw a window later, with update_screen(type).
+///
+/// Set must_redraw only if not already set to a higher value.
+/// e.g. if must_redraw is CLEAR, type NOT_VALID will do nothing.
+void redraw_later(win_T *wp, int type)
FUNC_ATTR_NONNULL_ALL
{
if (!exiting && wp->w_redr_type < type) {
@@ -223,7 +217,7 @@ void redraw_win_later(win_T *wp, int type)
void redraw_all_later(int type)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- redraw_win_later(wp, type);
+ redraw_later(wp, type);
}
// This may be needed when switching tabs.
if (must_redraw < type) {
@@ -234,7 +228,7 @@ void redraw_all_later(int type)
void screen_invalidate_highlights(void)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- redraw_win_later(wp, NOT_VALID);
+ redraw_later(wp, NOT_VALID);
wp->w_grid.valid = false;
}
}
@@ -251,7 +245,7 @@ void redraw_buf_later(buf_T *buf, int type)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_buffer == buf) {
- redraw_win_later(wp, type);
+ redraw_later(wp, type);
}
}
}
@@ -277,7 +271,7 @@ void redraw_buf_range_later(buf_T *buf, linenr_T firstline, linenr_T lastline)
if (wp->w_redraw_bot == 0 || wp->w_redraw_bot < lastline) {
wp->w_redraw_bot = lastline;
}
- redraw_win_later(wp, VALID);
+ redraw_later(wp, VALID);
}
}
}
@@ -305,7 +299,7 @@ redrawWinline(
if (wp->w_redraw_bot == 0 || wp->w_redraw_bot < lnum) {
wp->w_redraw_bot = lnum;
}
- redraw_win_later(wp, VALID);
+ redraw_later(wp, VALID);
}
}
@@ -359,7 +353,6 @@ int update_screen(int type)
/* Postpone the redrawing when it's not needed and when being called
* recursively. */
if (!redrawing() || updating_screen) {
- redraw_later(type); /* remember type for next time */
must_redraw = type;
if (type > INVERTED_ALL) {
curwin->w_lines_valid = 0; // don't use w_lines[].wl_size now
@@ -501,6 +494,12 @@ int update_screen(int type)
}
}
+ // "start" callback could have changed highlights for global elements
+ if (win_check_ns_hl(NULL)) {
+ redraw_cmdline = true;
+ redraw_tabline = true;
+ }
+
if (clear_cmdline) /* going to clear cmdline (done below) */
check_for_delay(FALSE);
@@ -1331,6 +1330,8 @@ static void win_update(win_T *wp, Providers *providers)
}
}
+ win_check_ns_hl(wp);
+
for (;; ) {
/* stop updating when reached the end of the window (check for _past_
@@ -2185,6 +2186,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
// return 'false' or error: skip rest of this window
kv_A(*providers, k) = NULL;
}
+
+ win_check_ns_hl(wp);
}
}
@@ -4649,8 +4652,8 @@ void status_redraw_all(void)
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_status_height) {
- wp->w_redr_status = TRUE;
- redraw_later(VALID);
+ wp->w_redr_status = true;
+ redraw_later(wp, VALID);
}
}
}
@@ -4667,7 +4670,7 @@ void status_redraw_buf(buf_T *buf)
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_status_height != 0 && wp->w_buffer == buf) {
wp->w_redr_status = true;
- redraw_later(VALID);
+ redraw_later(wp, VALID);
}
}
}
@@ -5191,8 +5194,8 @@ win_redr_custom (
char_u buf[MAXPATHL];
char_u *stl;
char_u *p;
- struct stl_hlrec hltab[STL_MAX_ITEM];
- StlClickRecord tabtab[STL_MAX_ITEM];
+ stl_hlrec_t *hltab;
+ StlClickRecord *tabtab;
int use_sandbox = false;
win_T *ewp;
int p_crb_save;
@@ -5270,9 +5273,9 @@ win_redr_custom (
/* Make a copy, because the statusline may include a function call that
* might change the option value and free the memory. */
stl = vim_strsave(stl);
- width = build_stl_str_hl(ewp, buf, sizeof(buf),
- stl, use_sandbox,
- fillchar, maxwidth, hltab, tabtab);
+ width =
+ build_stl_str_hl(ewp, buf, sizeof(buf), stl, use_sandbox,
+ fillchar, maxwidth, &hltab, &tabtab);
xfree(stl);
ewp->w_p_crb = p_crb_save;
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 9458e6333f..b25333c9fa 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -4923,7 +4923,7 @@ search_line:
&& curwin != curwin_save && win_valid(curwin_save)) {
/* Return cursor to where we were */
validate_cursor();
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
win_enter(curwin_save, true);
}
break;
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 1984a357c3..636c71657d 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -2258,7 +2258,7 @@ char_u *did_set_spelllang(win_T *wp)
theend:
xfree(spl_copy);
recursive = false;
- redraw_win_later(wp, NOT_VALID);
+ redraw_later(wp, NOT_VALID);
return ret_msg;
}
@@ -6877,7 +6877,7 @@ void ex_spelldump(exarg_T *eap)
if (curbuf->b_ml.ml_line_count > 1) {
ml_delete(curbuf->b_ml.ml_line_count, false);
}
- redraw_later(NOT_VALID);
+ redraw_later(curwin, NOT_VALID);
}
// Go through all possible words and:
diff --git a/src/nvim/spell_defs.h b/src/nvim/spell_defs.h
index 034c580b3e..05667f060e 100644
--- a/src/nvim/spell_defs.h
+++ b/src/nvim/spell_defs.h
@@ -119,6 +119,7 @@ struct slang_S {
bool sl_add; // true if it's a .add file.
char_u *sl_fbyts; // case-folded word bytes
+ long sl_fbyts_len; // length of sl_fbyts
idx_T *sl_fidxs; // case-folded word indexes
char_u *sl_kbyts; // keep-case word bytes
idx_T *sl_kidxs; // keep-case word indexes
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index 09d8646c6d..b415a4635b 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -764,20 +764,24 @@ truncerr:
}
// <LWORDTREE>
- res = spell_read_tree(fd, &lp->sl_fbyts, &lp->sl_fidxs, false, 0);
- if (res != 0)
+ res = spell_read_tree(fd, &lp->sl_fbyts, &lp->sl_fbyts_len,
+ &lp->sl_fidxs, false, 0);
+ if (res != 0) {
goto someerror;
+ }
// <KWORDTREE>
- res = spell_read_tree(fd, &lp->sl_kbyts, &lp->sl_kidxs, false, 0);
- if (res != 0)
+ res = spell_read_tree(fd, &lp->sl_kbyts, NULL, &lp->sl_kidxs, false, 0);
+ if (res != 0) {
goto someerror;
+ }
// <PREFIXTREE>
- res = spell_read_tree(fd, &lp->sl_pbyts, &lp->sl_pidxs, true,
- lp->sl_prefixcnt);
- if (res != 0)
+ res = spell_read_tree(fd, &lp->sl_pbyts, NULL, &lp->sl_pidxs, true,
+ lp->sl_prefixcnt);
+ if (res != 0) {
goto someerror;
+ }
// For a new file link it in the list of spell files.
if (old_lp == NULL && lang != NULL) {
@@ -920,8 +924,8 @@ void suggest_load_files(void)
// <SUGWORDTREE>: <wordtree>
// Read the trie with the soundfolded words.
- if (spell_read_tree(fd, &slang->sl_sbyts, &slang->sl_sidxs,
- false, 0) != 0) {
+ if (spell_read_tree(fd, &slang->sl_sbyts, NULL, &slang->sl_sidxs,
+ false, 0) != 0) {
someerror:
EMSG2(_("E782: error while reading .sug file: %s"),
slang->sl_fname);
@@ -1630,10 +1634,12 @@ static int
spell_read_tree (
FILE *fd,
char_u **bytsp,
+ long *bytsp_len,
idx_T **idxsp,
bool prefixtree, // true for the prefix tree
int prefixcnt // when "prefixtree" is true: prefix count
)
+ FUNC_ATTR_NONNULL_ARG(1, 2, 4)
{
int idx;
char_u *bp;
@@ -1653,6 +1659,9 @@ spell_read_tree (
// Allocate the byte array.
bp = xmalloc(len);
*bytsp = bp;
+ if (bytsp_len != NULL) {
+ *bytsp_len = len;
+ }
// Allocate the index array.
ip = xcalloc(len, sizeof(*ip));
@@ -4850,10 +4859,10 @@ static int sug_filltree(spellinfo_T *spin, slang_T *slang)
spin->si_blocks_cnt = 0;
// Skip over any other NUL bytes (same word with different
- // flags).
- while (byts[n + 1] == 0) {
- ++n;
- ++curi[depth];
+ // flags). But don't go over the end.
+ while (n + 1 < slang->sl_fbyts_len && byts[n + 1] == 0) {
+ n++;
+ curi[depth]++;
}
} else {
// Normal char, go one level deeper.
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 9a9cc45c6b..ec6accd473 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -73,9 +73,9 @@ struct hl_group {
RgbValue sg_rgb_fg; ///< RGB foreground color
RgbValue sg_rgb_bg; ///< RGB background color
RgbValue sg_rgb_sp; ///< RGB special color
- uint8_t *sg_rgb_fg_name; ///< RGB foreground color name
- uint8_t *sg_rgb_bg_name; ///< RGB background color name
- uint8_t *sg_rgb_sp_name; ///< RGB special color name
+ char *sg_rgb_fg_name; ///< RGB foreground color name
+ char *sg_rgb_bg_name; ///< RGB background color name
+ char *sg_rgb_sp_name; ///< RGB special color name
int sg_blend; ///< blend level (0-100 inclusive), -1 if unset
};
@@ -3147,7 +3147,7 @@ static void syn_cmd_spell(exarg_T *eap, int syncing)
}
// assume spell checking changed, force a redraw
- redraw_win_later(curwin, NOT_VALID);
+ redraw_later(curwin, NOT_VALID);
}
/// Handle ":syntax iskeyword" command.
@@ -3187,7 +3187,7 @@ static void syn_cmd_iskeyword(exarg_T *eap, int syncing)
curbuf->b_p_isk = save_isk;
}
}
- redraw_win_later(curwin, NOT_VALID);
+ redraw_later(curwin, NOT_VALID);
}
/*
@@ -4297,7 +4297,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
prev_toplvl_grp = curwin->w_s->b_syn_topgrp;
curwin->w_s->b_syn_topgrp = sgl_id;
if (source ? do_source(eap->arg, false, DOSO_NONE) == FAIL
- : source_runtime(eap->arg, DIP_ALL) == FAIL) {
+ : source_in_path(p_rtp, eap->arg, DIP_ALL) == FAIL) {
EMSG2(_(e_notopen), eap->arg);
}
curwin->w_s->b_syn_topgrp = prev_toplvl_grp;
@@ -6899,7 +6899,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
}
} else if (strcmp(key, "GUIFG") == 0) {
- char_u **const namep = &HL_TABLE()[idx].sg_rgb_fg_name;
+ char **namep = &HL_TABLE()[idx].sg_rgb_fg_name;
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
if (!init) {
@@ -6909,8 +6909,8 @@ void do_highlight(const char *line, const bool forceit, const bool init)
if (*namep == NULL || STRCMP(*namep, arg) != 0) {
xfree(*namep);
if (strcmp(arg, "NONE") != 0) {
- *namep = (char_u *)xstrdup(arg);
- HL_TABLE()[idx].sg_rgb_fg = name_to_color((char_u *)arg);
+ *namep = xstrdup(arg);
+ HL_TABLE()[idx].sg_rgb_fg = name_to_color(arg);
} else {
*namep = NULL;
HL_TABLE()[idx].sg_rgb_fg = -1;
@@ -6923,7 +6923,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
normal_fg = HL_TABLE()[idx].sg_rgb_fg;
}
} else if (STRCMP(key, "GUIBG") == 0) {
- char_u **const namep = &HL_TABLE()[idx].sg_rgb_bg_name;
+ char **const namep = &HL_TABLE()[idx].sg_rgb_bg_name;
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
if (!init) {
@@ -6933,8 +6933,8 @@ void do_highlight(const char *line, const bool forceit, const bool init)
if (*namep == NULL || STRCMP(*namep, arg) != 0) {
xfree(*namep);
if (STRCMP(arg, "NONE") != 0) {
- *namep = (char_u *)xstrdup(arg);
- HL_TABLE()[idx].sg_rgb_bg = name_to_color((char_u *)arg);
+ *namep = xstrdup(arg);
+ HL_TABLE()[idx].sg_rgb_bg = name_to_color(arg);
} else {
*namep = NULL;
HL_TABLE()[idx].sg_rgb_bg = -1;
@@ -6947,7 +6947,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
normal_bg = HL_TABLE()[idx].sg_rgb_bg;
}
} else if (strcmp(key, "GUISP") == 0) {
- char_u **const namep = &HL_TABLE()[idx].sg_rgb_sp_name;
+ char **const namep = &HL_TABLE()[idx].sg_rgb_sp_name;
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
if (!init) {
@@ -6957,8 +6957,8 @@ void do_highlight(const char *line, const bool forceit, const bool init)
if (*namep == NULL || STRCMP(*namep, arg) != 0) {
xfree(*namep);
if (strcmp(arg, "NONE") != 0) {
- *namep = (char_u *)xstrdup(arg);
- HL_TABLE()[idx].sg_rgb_sp = name_to_color((char_u *)arg);
+ *namep = xstrdup(arg);
+ HL_TABLE()[idx].sg_rgb_sp = name_to_color(arg);
} else {
*namep = NULL;
HL_TABLE()[idx].sg_rgb_sp = -1;
@@ -7152,13 +7152,32 @@ static void highlight_list_one(const int id)
msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name);
}
- if (!didh)
- highlight_list_arg(id, didh, LIST_STRING, 0, (char_u *)"cleared", "");
+ if (!didh) {
+ highlight_list_arg(id, didh, LIST_STRING, 0, "cleared", "");
+ }
if (p_verbose > 0) {
last_set_msg(sgp->sg_script_ctx);
}
}
+Dictionary get_global_hl_defs(void)
+{
+ Dictionary rv = ARRAY_DICT_INIT;
+ for (int i = 1; i <= highlight_ga.ga_len && !got_int; i++) {
+ Dictionary attrs = ARRAY_DICT_INIT;
+ struct hl_group *h = &HL_TABLE()[i - 1];
+ if (h->sg_attr > 0) {
+ attrs = hlattrs2dict(syn_attr2entry(h->sg_attr), true);
+ } else if (h->sg_link > 0) {
+ const char *link = (const char *)HL_TABLE()[h->sg_link - 1].sg_name;
+ PUT(attrs, "link", STRING_OBJ(cstr_to_string(link)));
+ }
+ PUT(rv, (const char *)h->sg_name, DICTIONARY_OBJ(attrs));
+ }
+
+ return rv;
+}
+
/// Outputs a highlight when doing ":hi MyHighlight"
///
/// @param type one of \ref LIST_XXX
@@ -7166,15 +7185,15 @@ static void highlight_list_one(const int id)
/// @param sarg string used if \p type == LIST_STRING
static bool highlight_list_arg(
const int id, bool didh, const int type, int iarg,
- char_u *const sarg, const char *const name)
+ char *const sarg, const char *const name)
{
- char_u buf[100];
+ char buf[100];
if (got_int) {
return false;
}
if (type == LIST_STRING ? (sarg != NULL) : (iarg != 0)) {
- char_u *ts = buf;
+ char *ts = buf;
if (type == LIST_INT) {
snprintf((char *)buf, sizeof(buf), "%d", iarg - 1);
} else if (type == LIST_STRING) {
@@ -7191,15 +7210,15 @@ static bool highlight_list_arg(
}
}
- (void)syn_list_header(didh, (int)(vim_strsize(ts) + STRLEN(name) + 1), id,
- false);
+ (void)syn_list_header(didh, (int)(vim_strsize((char_u *)ts) + STRLEN(name)
+ + 1), id, false);
didh = true;
if (!got_int) {
if (*name != NUL) {
MSG_PUTS_ATTR(name, HL_ATTR(HLF_D));
MSG_PUTS_ATTR("=", HL_ATTR(HLF_D));
}
- msg_outtrans(ts);
+ msg_outtrans((char_u *)ts);
}
}
return didh;
@@ -7378,7 +7397,7 @@ static void set_hl_attr(int idx)
at_en.rgb_sp_color = sgp->sg_rgb_sp_name ? sgp->sg_rgb_sp : -1;
at_en.hl_blend = sgp->sg_blend;
- sgp->sg_attr = hl_get_syn_attr(idx+1, at_en);
+ sgp->sg_attr = hl_get_syn_attr(0, idx+1, at_en);
// a cursor style uses this syn_id, make sure its attribute is updated.
if (cursor_mode_uses_syn_id(idx+1)) {
@@ -7541,11 +7560,17 @@ int syn_id2attr(int hl_id)
struct hl_group *sgp;
hl_id = syn_get_final_id(hl_id);
- sgp = &HL_TABLE()[hl_id - 1]; /* index is ID minus one */
+ int attr = ns_get_hl(-1, hl_id, false);
+ if (attr >= 0) {
+ return attr;
+ }
+ sgp = &HL_TABLE()[hl_id - 1]; // index is ID minus one
return sgp->sg_attr;
}
+
+
/*
* Translate a group ID to the final group ID (following links).
*/
@@ -7562,9 +7587,22 @@ int syn_get_final_id(int hl_id)
* Look out for loops! Break after 100 links.
*/
for (count = 100; --count >= 0; ) {
- sgp = &HL_TABLE()[hl_id - 1]; /* index is ID minus one */
- if (sgp->sg_link == 0 || sgp->sg_link > highlight_ga.ga_len)
+ // ACHTUNG: when using "tmp" attribute (no link) the function might be
+ // called twice. it needs be smart enough to remember attr only to
+ // syn_id2attr time
+ int check = ns_get_hl(-1, hl_id, true);
+ if (check == 0) {
+ return 0; // how dare! it broke the link!
+ } else if (check > 0) {
+ hl_id = check;
+ continue;
+ }
+
+
+ sgp = &HL_TABLE()[hl_id - 1]; // index is ID minus one
+ if (sgp->sg_link == 0 || sgp->sg_link > highlight_ga.ga_len) {
break;
+ }
hl_id = sgp->sg_link;
}
@@ -8494,7 +8532,7 @@ color_name_table_T color_name_table[] = {
///
/// @param[in] name string value to convert to RGB
/// return the hex value or -1 if could not find a correct value
-RgbValue name_to_color(const char_u *name)
+RgbValue name_to_color(const char *name)
{
if (name[0] == '#' && isxdigit(name[1]) && isxdigit(name[2])
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 81d1ef4c9f..c6b1a0d04c 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -2903,7 +2903,7 @@ static int jumpto_tag(
&& curwin != curwin_save && win_valid(curwin_save)) {
/* Return cursor to where we were */
validate_cursor();
- redraw_later(VALID);
+ redraw_later(curwin, VALID);
win_enter(curwin_save, true);
}
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 52d3eef810..39e2ca6171 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -233,7 +233,7 @@ Terminal *terminal_open(TerminalOptions opts)
snprintf(var, sizeof(var), "terminal_color_%d", i);
char *name = get_config_string(var);
if (name) {
- color_val = name_to_color((uint8_t *)name);
+ color_val = name_to_color(name);
xfree(name);
if (color_val != -1) {
@@ -1060,7 +1060,7 @@ static bool send_mouse_event(Terminal *term, int c)
curwin->w_redr_status = true;
curwin = save_curwin;
curbuf = curwin->w_buffer;
- redraw_win_later(mouse_win, NOT_VALID);
+ redraw_later(mouse_win, NOT_VALID);
invalidate_terminal(term, -1, -1);
// Only need to exit focus if the scrolled window is the terminal window
return mouse_win == curwin;
diff --git a/src/nvim/testdir/test_cindent.vim b/src/nvim/testdir/test_cindent.vim
index debc9da46d..b6c2d1467e 100644
--- a/src/nvim/testdir/test_cindent.vim
+++ b/src/nvim/testdir/test_cindent.vim
@@ -127,4 +127,40 @@ func Test_cindent_case()
bwipe!
endfunc
+func Test_cindent_pragma()
+ new
+ setl cindent ts=4 sw=4
+ setl cino=Ps
+
+ let code =<< trim [CODE]
+ {
+ #pragma omp parallel
+ {
+ #pragma omp task
+ foo();
+ # pragma omp taskwait
+ }
+ }
+ [CODE]
+
+ call append(0, code)
+ normal gg
+ normal =G
+
+ let expected =<< trim [CODE]
+ {
+ #pragma omp parallel
+ {
+ #pragma omp task
+ foo();
+ # pragma omp taskwait
+ }
+ }
+
+ [CODE]
+
+ call assert_equal(expected, getline(1, '$'))
+ enew! | close
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index 871143699a..e3c42a4fe3 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -722,7 +722,7 @@ func Test_verbosefile()
endfunc
func Test_verbose_option()
- " See test/functional/ui/cmdline_spec.lua
+ " See test/functional/legacy/cmdline_spec.lua
CheckScreendump
let lines =<< trim [SCRIPT]
@@ -842,6 +842,25 @@ func Test_buffers_lastused()
bwipeout bufc
endfunc
+func Test_cmdlineclear_tabenter()
+ " See test/functional/legacy/cmdline_spec.lua
+ CheckScreendump
+
+ let lines =<< trim [SCRIPT]
+ call setline(1, range(30))
+ [SCRIPT]
+
+ call writefile(lines, 'XtestCmdlineClearTabenter')
+ let buf = RunVimInTerminal('-S XtestCmdlineClearTabenter', #{rows: 10})
+ call term_wait(buf, 50)
+ " in one tab make the command line higher with CTRL-W -
+ call term_sendkeys(buf, ":tabnew\<cr>\<C-w>-\<C-w>-gtgt")
+ call VerifyScreenDump(buf, 'Test_cmdlineclear_tabenter', {})
+
+ call StopVimInTerminal(buf)
+ call delete('XtestCmdlineClearTabenter')
+endfunc
+
" test that ";" works to find a match at the start of the first line
func Test_zero_line_search()
new
diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim
index 15c718b243..abad6983dc 100644
--- a/src/nvim/testdir/test_edit.vim
+++ b/src/nvim/testdir/test_edit.vim
@@ -1587,4 +1587,11 @@ func Test_edit_browse()
bwipe!
endfunc
+func Test_read_invalid()
+ " set encoding=latin1
+ " This was not properly checking for going past the end.
+ call assert_fails('r`=', 'E484')
+ set encoding=utf-8
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_listdict.vim b/src/nvim/testdir/test_listdict.vim
index 31a8b48d37..8e2a987e74 100644
--- a/src/nvim/testdir/test_listdict.vim
+++ b/src/nvim/testdir/test_listdict.vim
@@ -199,9 +199,9 @@ func Test_dict_big()
try
let n = d[1500]
catch
- let str=substitute(v:exception, '\v(.{14}).*( \d{4}).*', '\1\2', '')
+ let str = substitute(v:exception, '\v(.{14}).*( "\d{4}").*', '\1\2', '')
endtry
- call assert_equal('Vim(let):E716: 1500', str)
+ call assert_equal('Vim(let):E716: "1500"', str)
" lookup each items
for i in range(1500)
diff --git a/src/nvim/testdir/test_messages.vim b/src/nvim/testdir/test_messages.vim
index ca14494248..30239a90c2 100644
--- a/src/nvim/testdir/test_messages.vim
+++ b/src/nvim/testdir/test_messages.vim
@@ -1,20 +1,16 @@
" Tests for :messages, :echomsg, :echoerr
-function Test_messages()
+source shared.vim
+
+func Test_messages()
let oldmore = &more
try
set nomore
- " Avoid the "message maintainer" line.
- let $LANG = ''
- let $LC_ALL = ''
- let $LC_MESSAGES = ''
- let $LC_COLLATE = ''
let arr = map(range(10), '"hello" . v:val')
for s in arr
echomsg s | redraw
endfor
- let result = ''
" get last two messages
redir => result
@@ -25,22 +21,17 @@ function Test_messages()
" clear messages without last one
1messages clear
- redir => result
- redraw | messages
- redir END
- let msg_list = split(result, "\n")
+ let msg_list = GetMessages()
call assert_equal(['hello9'], msg_list)
" clear all messages
messages clear
- redir => result
- redraw | messages
- redir END
- call assert_equal('', result)
+ let msg_list = GetMessages()
+ call assert_equal([], msg_list)
finally
let &more = oldmore
endtry
-endfunction
+endfunc
" Patch 7.4.1696 defined the "clearmode()" command for clearing the mode
" indicator (e.g., "-- INSERT --") when ":stopinsert" is invoked. Message
diff --git a/src/nvim/testdir/test_mksession.vim b/src/nvim/testdir/test_mksession.vim
index 3243edbf55..215065f941 100644
--- a/src/nvim/testdir/test_mksession.vim
+++ b/src/nvim/testdir/test_mksession.vim
@@ -470,4 +470,17 @@ func Test_mkvimrc()
call delete('Xtestvimrc')
endfunc
+func Test_scrolloff()
+ set sessionoptions+=localoptions
+ setlocal so=1 siso=1
+ mksession! Xtest_mks.out
+ setlocal so=-1 siso=-1
+ source Xtest_mks.out
+ call assert_equal(1, &l:so)
+ call assert_equal(1, &l:siso)
+ call delete('Xtest_mks.out')
+ setlocal so& siso&
+ set sessionoptions&
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index 9e8da74db7..10e16f4198 100644
--- a/src/nvim/testdir/test_options.vim
+++ b/src/nvim/testdir/test_options.vim
@@ -267,7 +267,6 @@ func Test_set_errors()
call assert_fails('set commentstring=x', 'E537:')
call assert_fails('set complete=x', 'E539:')
call assert_fails('set statusline=%{', 'E540:')
- call assert_fails('set statusline=' . repeat("%p", 81), 'E541:')
call assert_fails('set statusline=%(', 'E542:')
if has('cursorshape')
" This invalid value for 'guicursor' used to cause Vim to crash.
diff --git a/src/nvim/testdir/test_registers.vim b/src/nvim/testdir/test_registers.vim
index d20f8d1eef..19a7c6c9d0 100644
--- a/src/nvim/testdir/test_registers.vim
+++ b/src/nvim/testdir/test_registers.vim
@@ -167,6 +167,75 @@ func Test_set_register()
enew!
endfunc
+func Test_v_register()
+ enew
+ call setline(1, 'nothing')
+
+ func s:Put()
+ let s:register = v:register
+ exec 'normal! "' .. v:register .. 'P'
+ endfunc
+ nnoremap <buffer> <plug>(test) :<c-u>call s:Put()<cr>
+ nmap <buffer> S <plug>(test)
+
+ let @z = "testz\n"
+ let @" = "test@\n"
+
+ let s:register = ''
+ call feedkeys('"_ddS', 'mx')
+ call assert_equal('test@', getline('.')) " fails before 8.2.0929
+ call assert_equal('"', s:register) " fails before 8.2.0929
+
+ let s:register = ''
+ call feedkeys('"zS', 'mx')
+ call assert_equal('z', s:register)
+
+ let s:register = ''
+ call feedkeys('"zSS', 'mx')
+ call assert_equal('"', s:register)
+
+ let s:register = ''
+ call feedkeys('"_S', 'mx')
+ call assert_equal('_', s:register)
+
+ let s:register = ''
+ normal "_ddS
+ call assert_equal('"', s:register) " fails before 8.2.0929
+ call assert_equal('test@', getline('.')) " fails before 8.2.0929
+
+ let s:register = ''
+ execute 'normal "z:call' "s:Put()\n"
+ call assert_equal('z', s:register)
+ call assert_equal('testz', getline('.'))
+
+ " Test operator and omap
+ let @b = 'testb'
+ func s:OpFunc(...)
+ let s:register2 = v:register
+ endfunc
+ set opfunc=s:OpFunc
+
+ normal "bg@l
+ normal S
+ call assert_equal('"', s:register) " fails before 8.2.0929
+ call assert_equal('b', s:register2)
+
+ func s:Motion()
+ let s:register1 = v:register
+ normal! l
+ endfunc
+ onoremap <buffer> Q :<c-u>call s:Motion()<cr>
+
+ normal "bg@Q
+ normal S
+ call assert_equal('"', s:register)
+ call assert_equal('b', s:register1)
+ call assert_equal('"', s:register2)
+
+ set opfunc&
+ bwipe!
+endfunc
+
func Test_ve_blockpaste()
new
set ve=all
diff --git a/src/nvim/testdir/test_ruby.vim b/src/nvim/testdir/test_ruby.vim
index 07ad8561c3..9c74c35049 100644
--- a/src/nvim/testdir/test_ruby.vim
+++ b/src/nvim/testdir/test_ruby.vim
@@ -1,8 +1,7 @@
" Tests for ruby interface
-if !has('ruby')
- finish
-end
+source check.vim
+CheckFeature ruby
func Test_ruby_change_buffer()
call setline(line('$'), ['1 line 1'])
@@ -36,7 +35,7 @@ func Test_rubyfile()
call delete(tempfile)
endfunc
-func Test_set_cursor()
+func Test_ruby_set_cursor()
" Check that setting the cursor position works.
new
call setline(1, ['first line', 'second line'])
@@ -56,7 +55,7 @@ func Test_set_cursor()
endfunc
" Test buffer.count and buffer.length (number of lines in buffer)
-func Test_buffer_count()
+func Test_ruby_buffer_count()
new
call setline(1, ['one', 'two', 'three'])
call assert_equal(3, rubyeval('$curbuf.count'))
@@ -65,7 +64,7 @@ func Test_buffer_count()
endfunc
" Test buffer.name (buffer name)
-func Test_buffer_name()
+func Test_ruby_buffer_name()
new Xfoo
call assert_equal(expand('%:p'), rubyeval('$curbuf.name'))
bwipe
@@ -73,7 +72,7 @@ func Test_buffer_name()
endfunc
" Test buffer.number (number of the buffer).
-func Test_buffer_number()
+func Test_ruby_buffer_number()
new
call assert_equal(bufnr('%'), rubyeval('$curbuf.number'))
new
@@ -83,7 +82,7 @@ func Test_buffer_number()
endfunc
" Test buffer.delete({n}) (delete line {n})
-func Test_buffer_delete()
+func Test_ruby_buffer_delete()
new
call setline(1, ['one', 'two', 'three'])
ruby $curbuf.delete(2)
@@ -97,7 +96,7 @@ func Test_buffer_delete()
endfunc
" Test buffer.append({str}, str) (append line {str} after line {n})
-func Test_buffer_append()
+func Test_ruby_buffer_append()
new
ruby $curbuf.append(0, 'one')
ruby $curbuf.append(1, 'three')
@@ -117,7 +116,7 @@ func Test_buffer_append()
endfunc
" Test buffer.line (get or set the current line)
-func Test_buffer_line()
+func Test_ruby_buffer_line()
new
call setline(1, ['one', 'two', 'three'])
2
@@ -130,7 +129,7 @@ func Test_buffer_line()
endfunc
" Test buffer.line_number (get current line number)
-func Test_buffer_line_number()
+func Test_ruby_buffer_line_number()
new
call setline(1, ['one', 'two', 'three'])
2
@@ -139,7 +138,7 @@ func Test_buffer_line_number()
bwipe!
endfunc
-func Test_buffer_get()
+func Test_ruby_buffer_get()
new
call setline(1, ['one', 'two'])
call assert_equal('one', rubyeval('$curbuf[1]'))
@@ -153,7 +152,7 @@ func Test_buffer_get()
bwipe!
endfunc
-func Test_buffer_set()
+func Test_ruby_buffer_set()
new
call setline(1, ['one', 'two'])
ruby $curbuf[2] = 'TWO'
@@ -169,7 +168,7 @@ func Test_buffer_set()
endfunc
" Test window.width (get or set window height).
-func Test_window_height()
+func Test_ruby_window_height()
new
" Test setting window height
@@ -183,7 +182,7 @@ func Test_window_height()
endfunc
" Test window.width (get or set window width).
-func Test_window_width()
+func Test_ruby_window_width()
vnew
" Test setting window width
@@ -197,7 +196,7 @@ func Test_window_width()
endfunc
" Test window.buffer (get buffer object of a window object).
-func Test_window_buffer()
+func Test_ruby_window_buffer()
new Xfoo1
new Xfoo2
ruby $b2 = $curwin.buffer
@@ -216,14 +215,14 @@ func Test_window_buffer()
endfunc
" Test Vim::Window.current (get current window object)
-func Test_Vim_window_current()
+func Test_ruby_Vim_window_current()
let cw = rubyeval('$curwin.to_s')
" call assert_equal(cw, rubyeval('Vim::Window.current'))
call assert_match('^#<Neovim::Window:0x\x\+>$', cw)
endfunc
" Test Vim::Window.count (number of windows)
-func Test_Vim_window_count()
+func Test_ruby_Vim_window_count()
new Xfoo1
new Xfoo2
split
@@ -233,7 +232,7 @@ func Test_Vim_window_count()
endfunc
" Test Vim::Window[n] (get window object of window n)
-func Test_Vim_window_get()
+func Test_ruby_Vim_window_get()
new Xfoo1
new Xfoo2
call assert_match('Xfoo2$', rubyeval('Vim::Window[0].buffer.name'))
@@ -245,14 +244,14 @@ func Test_Vim_window_get()
endfunc
" Test Vim::Buffer.current (return the buffer object of current buffer)
-func Test_Vim_buffer_current()
+func Test_ruby_Vim_buffer_current()
let cb = rubyeval('$curbuf.to_s')
" call assert_equal(cb, rubyeval('Vim::Buffer.current'))
call assert_match('^#<Neovim::Buffer:0x\x\+>$', cb)
endfunc
" Test Vim::Buffer:.count (return the number of buffers)
-func Test_Vim_buffer_count()
+func Test_ruby_Vim_buffer_count()
new Xfoo1
new Xfoo2
call assert_equal(3, rubyeval('Vim::Buffer.count'))
@@ -261,7 +260,7 @@ func Test_Vim_buffer_count()
endfunc
" Test Vim::buffer[n] (return the buffer object of buffer number n)
-func Test_Vim_buffer_get()
+func Test_ruby_Vim_buffer_get()
new Xfoo1
new Xfoo2
@@ -276,7 +275,7 @@ endfunc
" Test Vim::command({cmd}) (execute a Ex command))
" Test Vim::command({cmd})
-func Test_Vim_command()
+func Test_ruby_Vim_command()
new
call setline(1, ['one', 'two', 'three', 'four'])
ruby Vim::command('2,3d')
@@ -285,7 +284,7 @@ func Test_Vim_command()
endfunc
" Test Vim::set_option (set a vim option)
-func Test_Vim_set_option()
+func Test_ruby_Vim_set_option()
call assert_equal(0, &number)
ruby Vim::set_option('number')
call assert_equal(1, &number)
@@ -293,14 +292,16 @@ func Test_Vim_set_option()
call assert_equal(0, &number)
endfunc
-func Test_Vim_evaluate()
+func Test_ruby_Vim_evaluate()
call assert_equal(123, rubyeval('Vim::evaluate("123")'))
" Vim::evaluate("123").class gives Integer or Fixnum depending
" on versions of Ruby.
call assert_match('^Integer\|Fixnum$', rubyeval('Vim::evaluate("123").class'))
- call assert_equal(1.23, rubyeval('Vim::evaluate("1.23")'))
- call assert_equal('Float', rubyeval('Vim::evaluate("1.23").class'))
+ if has('float')
+ call assert_equal(1.23, rubyeval('Vim::evaluate("1.23")'))
+ call assert_equal('Float', rubyeval('Vim::evaluate("1.23").class'))
+ endif
call assert_equal('foo', rubyeval('Vim::evaluate("\"foo\"")'))
call assert_equal('String', rubyeval('Vim::evaluate("\"foo\"").class'))
@@ -323,7 +324,7 @@ func Test_Vim_evaluate()
call assert_equal('FalseClass',rubyeval('Vim::evaluate("v:false").class'))
endfunc
-func Test_Vim_evaluate_list()
+func Test_ruby_Vim_evaluate_list()
call setline(line('$'), ['2 line 2'])
ruby Vim.command("normal /^2\n")
let l = ["abc", "def"]
@@ -337,7 +338,7 @@ EOF
call assert_equal('abc/def', getline('$'))
endfunc
-func Test_Vim_evaluate_dict()
+func Test_ruby_Vim_evaluate_dict()
let d = {'a': 'foo', 'b': 123}
redir => l:out
ruby d = Vim.evaluate("d"); print d
@@ -346,14 +347,14 @@ func Test_Vim_evaluate_dict()
endfunc
" Test Vim::message({msg}) (display message {msg})
-func Test_Vim_message()
+func Test_ruby_Vim_message()
throw 'skipped: TODO: '
ruby Vim::message('A message')
let messages = split(execute('message'), "\n")
call assert_equal('A message', messages[-1])
endfunc
-func Test_print()
+func Test_ruby_print()
func RubyPrint(expr)
return trim(execute('ruby print ' . a:expr))
endfunc
@@ -372,9 +373,9 @@ func Test_print()
delfunc RubyPrint
endfunc
-func Test_p()
+func Test_ruby_p()
ruby p 'Just a test'
- let messages = split(execute('message'), "\n")
+ let messages = GetMessages()
call assert_equal('"Just a test"', messages[-1])
" Check return values of p method
@@ -387,6 +388,6 @@ func Test_p()
messages clear
call assert_equal(v:true, rubyeval('p() == nil'))
- let messages = split(execute('message'), "\n")
+ let messages = GetMessages()
call assert_equal(0, len(messages))
endfunc
diff --git a/src/nvim/testdir/test_statusline.vim b/src/nvim/testdir/test_statusline.vim
index 7efd181d04..4e38f7ebd8 100644
--- a/src/nvim/testdir/test_statusline.vim
+++ b/src/nvim/testdir/test_statusline.vim
@@ -354,6 +354,21 @@ func Test_statusline()
delfunc GetNested
delfunc GetStatusLine
+ " Test statusline works with 80+ items
+ function! StatusLabel()
+ redrawstatus
+ return '[label]'
+ endfunc
+ let statusline = '%{StatusLabel()}'
+ for i in range(150)
+ let statusline .= '%#TabLine' . (i % 2 == 0 ? 'Fill' : 'Sel') . '#' . string(i)[0]
+ endfor
+ let &statusline = statusline
+ redrawstatus
+ set statusline&
+ delfunc StatusLabel
+
+
" Check statusline in current and non-current window
" with the 'fillchars' option.
set fillchars=stl:^,stlnc:=,vert:\|,fold:-,diff:-
diff --git a/src/nvim/types.h b/src/nvim/types.h
index a3d87f35ca..17f7e16740 100644
--- a/src/nvim/types.h
+++ b/src/nvim/types.h
@@ -21,7 +21,7 @@ typedef int handle_T;
// absent callback etc.
typedef int LuaRef;
-typedef uint64_t NS;
+typedef handle_T NS;
typedef struct expand expand_T;
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c
index e582d8f859..325ad31eaf 100644
--- a/src/nvim/ui_compositor.c
+++ b/src/nvim/ui_compositor.c
@@ -26,6 +26,7 @@
#include "nvim/screen.h"
#include "nvim/syntax.h"
#include "nvim/api/private/helpers.h"
+#include "nvim/lua/executor.h"
#include "nvim/os/os.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 6c5a6cdb46..a8b8f7aa50 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -2455,7 +2455,7 @@ static void u_undo_end(
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_buffer == curbuf && wp->w_p_cole > 0) {
- redraw_win_later(wp, NOT_VALID);
+ redraw_later(wp, NOT_VALID);
}
}
}
diff --git a/src/nvim/vim.h b/src/nvim/vim.h
index 832703e83d..873bef32d3 100644
--- a/src/nvim/vim.h
+++ b/src/nvim/vim.h
@@ -259,7 +259,6 @@ enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext()
#define PERROR(msg) (void) emsgf("%s: %s", msg, strerror(errno))
#define SHOWCMD_COLS 10 // columns needed by shown command
-#define STL_MAX_ITEM 80 // max nr of %<flag> in statusline
#include "nvim/path.h"
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 4931221e7a..2147bd4fc7 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -606,7 +606,7 @@ win_T *win_new_float(win_T *wp, FloatConfig fconfig, Error *err)
win_config_float(wp, fconfig);
wp->w_pos_changed = true;
- redraw_win_later(wp, VALID);
+ redraw_later(wp, VALID);
return wp;
}
@@ -679,7 +679,7 @@ void win_config_float(win_T *wp, FloatConfig fconfig)
wp->w_pos_changed = true;
if (change_external) {
wp->w_hl_needs_update = true;
- redraw_win_later(wp, NOT_VALID);
+ redraw_later(wp, NOT_VALID);
}
}
@@ -764,7 +764,7 @@ static void ui_ext_win_position(win_T *wp)
wp->w_grid.focusable = wp->w_float_config.focusable;
if (!valid) {
wp->w_grid.valid = false;
- redraw_win_later(wp, NOT_VALID);
+ redraw_later(wp, NOT_VALID);
}
}
} else {
@@ -1492,8 +1492,8 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
// Both windows need redrawing. Update all status lines, in case they
// show something related to the window count or position.
- redraw_win_later(wp, NOT_VALID);
- redraw_win_later(oldwin, NOT_VALID);
+ redraw_later(wp, NOT_VALID);
+ redraw_later(oldwin, NOT_VALID);
status_redraw_all();
if (need_status) {
@@ -1823,8 +1823,8 @@ static void win_exchange(long Prenum)
(void)win_comp_pos(); /* recompute window positions */
win_enter(wp, true);
- redraw_later(NOT_VALID);
- redraw_win_later(wp, NOT_VALID);
+ redraw_later(curwin, NOT_VALID);
+ redraw_later(wp, NOT_VALID);
}
// rotate windows: if upwards true the second window becomes the first one
@@ -1996,8 +1996,8 @@ void win_move_after(win_T *win1, win_T *win2)
win_append(win2, win1);
frame_append(win2->w_frame, win1->w_frame);
- (void)win_comp_pos(); /* recompute w_winrow for all windows */
- redraw_later(NOT_VALID);
+ (void)win_comp_pos(); // recompute w_winrow for all windows
+ redraw_later(curwin, NOT_VALID);
}
win_enter(win1, false);
@@ -3635,7 +3635,7 @@ void curwin_init(void)
void win_init_empty(win_T *wp)
{
- redraw_win_later(wp, NOT_VALID);
+ redraw_later(wp, NOT_VALID);
wp->w_lines_valid = 0;
wp->w_cursor.lnum = 1;
wp->w_curswant = wp->w_cursor.col = 0;
@@ -4049,7 +4049,7 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, int trigger_enter_au
prevwin = next_prevwin;
last_status(false); // status line may appear or disappear
- (void)win_comp_pos(); // recompute w_winrow for all windows
+ const int row = win_comp_pos(); // recompute w_winrow for all windows
diff_need_scrollbind = true;
/* The tabpage line may have appeared or disappeared, may need to resize
@@ -4060,11 +4060,20 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, int trigger_enter_au
clear_cmdline = true;
}
p_ch = curtab->tp_ch_used;
- if (curtab->tp_old_Rows != Rows || (old_off != firstwin->w_winrow
- ))
+
+ // When cmdheight is changed in a tab page with '<C-w>-', cmdline_row is
+ // changed but p_ch and tp_ch_used are not changed. Thus we also need to
+ // check cmdline_row.
+ if ((row < cmdline_row) && (cmdline_row <= Rows - p_ch)) {
+ clear_cmdline = true;
+ }
+
+ if (curtab->tp_old_Rows != Rows || (old_off != firstwin->w_winrow)) {
shell_new_rows();
- if (curtab->tp_old_Columns != Columns && starting == 0)
- shell_new_columns(); /* update window widths */
+ }
+ if (curtab->tp_old_Columns != Columns && starting == 0) {
+ shell_new_columns(); // update window widths
+ }
lastused_tabpage = old_curtab;
@@ -4587,10 +4596,11 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid,
}
maketitle();
- curwin->w_redr_status = TRUE;
- redraw_tabline = TRUE;
- if (restart_edit)
- redraw_later(VALID); /* causes status line redraw */
+ curwin->w_redr_status = true;
+ redraw_tabline = true;
+ if (restart_edit) {
+ redraw_later(curwin, VALID); // causes status line redraw
+ }
if (HL_ATTR(HLF_INACTIVE)
|| (prevwin && prevwin->w_hl_ids[HLF_INACTIVE])
@@ -5056,7 +5066,7 @@ static void frame_comp_pos(frame_T *topfrp, int *row, int *col)
/* position changed, redraw */
wp->w_winrow = *row;
wp->w_wincol = *col;
- redraw_win_later(wp, NOT_VALID);
+ redraw_later(wp, NOT_VALID);
wp->w_redr_status = true;
wp->w_pos_changed = true;
}
@@ -5109,7 +5119,7 @@ void win_setheight_win(int height, win_T *win)
if (win->w_floating) {
win->w_float_config.height = height;
win_config_float(win, win->w_float_config);
- redraw_win_later(win, NOT_VALID);
+ redraw_later(win, NOT_VALID);
} else {
frame_setheight(win->w_frame, height + win->w_status_height);
@@ -5312,7 +5322,7 @@ void win_setwidth_win(int width, win_T *wp)
if (wp->w_floating) {
wp->w_float_config.width = width;
win_config_float(wp, wp->w_float_config);
- redraw_win_later(wp, NOT_VALID);
+ redraw_later(wp, NOT_VALID);
} else {
frame_setwidth(wp->w_frame, width + wp->w_vsep_width);
@@ -5845,8 +5855,8 @@ void scroll_to_fraction(win_T *wp, int prev_height)
}
win_comp_scroll(wp);
- redraw_win_later(wp, SOME_VALID);
- wp->w_redr_status = TRUE;
+ redraw_later(wp, SOME_VALID);
+ wp->w_redr_status = true;
invalidate_botline_win(wp);
}
@@ -5885,7 +5895,7 @@ void win_set_inner_size(win_T *wp)
if (!exiting) {
scroll_to_fraction(wp, prev_height);
}
- redraw_win_later(wp, NOT_VALID); // SOME_VALID??
+ redraw_later(wp, NOT_VALID); // SOME_VALID??
}
if (width != wp->w_width_inner) {
@@ -5897,7 +5907,7 @@ void win_set_inner_size(win_T *wp)
update_topline();
curs_columns(true); // validate w_wrow
}
- redraw_win_later(wp, NOT_VALID);
+ redraw_later(wp, NOT_VALID);
}
if (wp->w_buffer->terminal) {
@@ -6741,7 +6751,7 @@ int match_add(win_T *wp, const char *const grp, const char *const pat,
prev->next = m;
m->next = cur;
- redraw_win_later(wp, rtype);
+ redraw_later(wp, rtype);
return id;
fail:
@@ -6799,7 +6809,7 @@ int match_delete(win_T *wp, int id, int perr)
rtype = VALID;
}
xfree(cur);
- redraw_win_later(wp, rtype);
+ redraw_later(wp, rtype);
return 0;
}
@@ -6817,7 +6827,7 @@ void clear_matches(win_T *wp)
xfree(wp->w_match_head);
wp->w_match_head = m;
}
- redraw_win_later(wp, SOME_VALID);
+ redraw_later(wp, SOME_VALID);
}
/*
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index 9b0668f9e6..3bfae5f3d7 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -7,6 +7,7 @@ local ok = helpers.ok
local eq = helpers.eq
local matches = helpers.matches
local eval = helpers.eval
+local exec_lua = helpers.exec_lua
local feed = helpers.feed
local funcs = helpers.funcs
local mkdir = helpers.mkdir
@@ -305,6 +306,27 @@ describe('startup', function()
'+q' })
eq('[\'+q\'] 1', out)
end)
+
+ local function pack_clear(cmd)
+ clear('--cmd', 'set packpath=test/functional/fixtures', '--cmd', cmd)
+ end
+
+
+ it("handles &packpath during startup", function()
+ pack_clear [[ let g:x = bar#test() ]]
+ eq(-3, eval 'g:x')
+
+ pack_clear [[ lua _G.y = require'bar'.doit() ]]
+ eq(9003, exec_lua [[ return _G.y ]])
+ end)
+
+ it("handles :packadd during startup", function()
+ pack_clear [[ packadd! bonus | let g:x = bonus#secret() ]]
+ eq('halloj', eval 'g:x')
+
+ pack_clear [[ packadd! bonus | lua _G.y = require'bonus'.launch() ]]
+ eq('CPE 1704 TKS', exec_lua [[ return _G.y ]])
+ end)
end)
describe('sysinit', function()
diff --git a/test/functional/eval/null_spec.lua b/test/functional/eval/null_spec.lua
index db0a706319..fa8f7d873f 100644
--- a/test/functional/eval/null_spec.lua
+++ b/test/functional/eval/null_spec.lua
@@ -132,7 +132,7 @@ describe('NULL', function()
end)
describe('dict', function()
it('does not crash when indexing NULL dict', function()
- eq('\nE716: Key not present in Dictionary: test\nE15: Invalid expression: v:_null_dict.test',
+ eq('\nE716: Key not present in Dictionary: "test"\nE15: Invalid expression: v:_null_dict.test',
redir_exec('echo v:_null_dict.test'))
end)
null_expr_test('makes extend error out', 'extend(D, {})', 'E742: Cannot change value of extend() argument', 0)
diff --git a/test/functional/ex_cmds/packadd_spec.lua b/test/functional/ex_cmds/packadd_spec.lua
deleted file mode 100644
index 2b0810cf9b..0000000000
--- a/test/functional/ex_cmds/packadd_spec.lua
+++ /dev/null
@@ -1,74 +0,0 @@
-local helpers = require('test.functional.helpers')(after_each)
-
-local clear = helpers.clear
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
-
-describe('packadd', function()
- before_each(function()
- -- Primarily taken from test/functional/legacy/packadd_spec.lua
- clear()
- exec_lua [[
- TopDirectory = vim.fn.expand(vim.fn.getcwd() .. '/Xdir_lua')
- PlugDirectory = TopDirectory .. '/pack/mine/opt/mytest'
-
- vim.o.packpath = TopDirectory
-
- function FindPathsContainingDir(dir)
- return vim.fn.filter(
- vim.split(package.path, ';'),
- function(k, v)
- return string.find(v, 'mytest') ~= nil
- end
- )
- end
- ]]
- end)
-
- after_each(function()
- exec_lua [[
- vim.fn.delete(TopDirectory, 'rf')
- ]]
- end)
-
- it('should immediately update package.path in lua', function()
- local count_of_paths = exec_lua [[
- vim.fn.mkdir(PlugDirectory .. '/lua/', 'p')
-
- local num_paths_before = #FindPathsContainingDir('mytest')
-
- vim.cmd("packadd mytest")
-
- local num_paths_after = #FindPathsContainingDir('mytest')
-
- return { num_paths_before, num_paths_after }
- ]]
-
- eq({0, 2}, count_of_paths)
- end)
-
- it('should immediately update package.path in lua even if lua directory does not exist', function()
- local count_of_paths = exec_lua [[
- vim.fn.mkdir(PlugDirectory .. '/plugin/', 'p')
-
- local num_paths_before = #FindPathsContainingDir('mytest')
-
- vim.cmd("packadd mytest")
-
- local num_paths_after = #FindPathsContainingDir('mytest')
-
- return { num_paths_before, num_paths_after }
- ]]
-
- eq({0, 2}, count_of_paths)
- end)
-
- it('should error for invalid paths', function()
- local count_of_paths = exec_lua [[
- local ok, err = pcall(vim.cmd, "packadd asdf")
- return ok
- ]]
-
- eq(false, count_of_paths)
- end)
-end)
diff --git a/test/functional/fixtures/pack/foo/opt/bonus/autoload/bonus.vim b/test/functional/fixtures/pack/foo/opt/bonus/autoload/bonus.vim
new file mode 100644
index 0000000000..5ed8b1b887
--- /dev/null
+++ b/test/functional/fixtures/pack/foo/opt/bonus/autoload/bonus.vim
@@ -0,0 +1,3 @@
+func bonus#secret()
+ return "halloj"
+endfunc
diff --git a/test/functional/fixtures/pack/foo/opt/bonus/lua/bonus.lua b/test/functional/fixtures/pack/foo/opt/bonus/lua/bonus.lua
new file mode 100644
index 0000000000..52cb0bc118
--- /dev/null
+++ b/test/functional/fixtures/pack/foo/opt/bonus/lua/bonus.lua
@@ -0,0 +1 @@
+return {launch=function() return "CPE 1704 TKS" end}
diff --git a/test/functional/fixtures/pack/foo/start/bar/autoload/bar.vim b/test/functional/fixtures/pack/foo/start/bar/autoload/bar.vim
new file mode 100644
index 0000000000..405e7be71c
--- /dev/null
+++ b/test/functional/fixtures/pack/foo/start/bar/autoload/bar.vim
@@ -0,0 +1,3 @@
+func bar#test()
+ return -3
+endfunc
diff --git a/test/functional/fixtures/pack/foo/start/bar/lua/bar.lua b/test/functional/fixtures/pack/foo/start/bar/lua/bar.lua
new file mode 100644
index 0000000000..a7e9a61e35
--- /dev/null
+++ b/test/functional/fixtures/pack/foo/start/bar/lua/bar.lua
@@ -0,0 +1 @@
+return {doit=function() return 9003 end}
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 0bd378d832..d85a6a3cfe 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -751,6 +751,14 @@ module.curbufmeths = module.create_callindex(module.curbuf)
module.curwinmeths = module.create_callindex(module.curwin)
module.curtabmeths = module.create_callindex(module.curtab)
+function module.exec(code)
+ return module.meths.exec(code, false)
+end
+
+function module.exec_capture(code)
+ return module.meths.exec(code, true)
+end
+
function module.exec_lua(code, ...)
return module.meths.exec_lua(code, {...})
end
diff --git a/test/functional/legacy/055_list_and_dict_types_spec.lua b/test/functional/legacy/055_list_and_dict_types_spec.lua
index 91ba8bb106..4d71a526c1 100644
--- a/test/functional/legacy/055_list_and_dict_types_spec.lua
+++ b/test/functional/legacy/055_list_and_dict_types_spec.lua
@@ -229,7 +229,7 @@ describe('list and dictionary types', function()
try
let n = d[1500]
catch
- $put =substitute(v:exception, '\v(.{14}).*( \d{4}).*', '\1\2', '')
+ $put = substitute(v:exception, '\v(.{14}).*( \"\d{4}\").*', '\1\2', '')
endtry
" Lookup each items.
for i in range(1500)
@@ -260,7 +260,7 @@ describe('list and dictionary types', function()
expect([[
3000 2900 2001 1600 1501
- Vim(let):E716: 1500
+ Vim(let):E716: "1500"
NONE 2999
33=999
{'33': 999}]])
diff --git a/test/functional/legacy/cmdline_spec.lua b/test/functional/legacy/cmdline_spec.lua
new file mode 100644
index 0000000000..9ebe9aeb91
--- /dev/null
+++ b/test/functional/legacy/cmdline_spec.lua
@@ -0,0 +1,66 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear = helpers.clear
+local feed = helpers.feed
+local feed_command = helpers.feed_command
+local source = helpers.source
+
+describe('cmdline', function()
+ before_each(clear)
+
+ it('is cleared when switching tabs', function()
+ local screen = Screen.new(30, 10)
+ screen:attach()
+ feed_command([[call setline(1, range(30))]])
+ screen:expect([[
+ ^0 |
+ 1 |
+ 2 |
+ 3 |
+ 4 |
+ 5 |
+ 6 |
+ 7 |
+ 8 |
+ :call setline(1, range(30)) |
+ ]])
+ feed([[:tabnew<cr><C-w>-<C-w>-gtgt]])
+ screen:expect([[
+ + [No Name] [No Name] X|
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ 6 |
+ 7 |
+ |
+ ]])
+ end)
+
+ it('prints every executed Ex command if verbose >= 16', function()
+ local screen = Screen.new(60, 12)
+ screen:attach()
+ source([[
+ command DoSomething echo 'hello' |set ts=4 |let v = '123' |echo v
+ call feedkeys("\r", 't') " for the hit-enter prompt
+ set verbose=20
+ ]])
+ feed_command('DoSomething')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ |
+ Executing: DoSomething |
+ Executing: echo 'hello' |set ts=4 |let v = '123' |echo v |
+ hello |
+ Executing: set ts=4 |let v = '123' |echo v |
+ Executing: let v = '123' |echo v |
+ Executing: echo v |
+ 123 |
+ Press ENTER or type command to continue^ |
+ ]])
+ end)
+end)
diff --git a/test/functional/lua/overrides_spec.lua b/test/functional/lua/overrides_spec.lua
index 1bccc02847..5fbba63736 100644
--- a/test/functional/lua/overrides_spec.lua
+++ b/test/functional/lua/overrides_spec.lua
@@ -285,119 +285,6 @@ describe('debug.debug', function()
end)
end)
-describe('package.path/package.cpath', function()
- local sl = alter_slashes
-
- local function get_new_paths(sufs, runtimepaths)
- runtimepaths = runtimepaths or meths.list_runtime_paths()
- local new_paths = {}
- local sep = package.config:sub(1, 1)
- for _, v in ipairs(runtimepaths) do
- for _, suf in ipairs(sufs) do
- new_paths[#new_paths + 1] = v .. sep .. 'lua' .. suf
- end
- end
- return new_paths
- end
- local function eval_lua(expr, ...)
- return meths.exec_lua('return '..expr, {...})
- end
- local function set_path(which, value)
- return exec_lua('package[select(1, ...)] = select(2, ...)', which, value)
- end
-
- it('contains directories from &runtimepath on first invocation', function()
- local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'})
- local new_paths_str = table.concat(new_paths, ';')
- eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str))
-
- local new_cpaths = get_new_paths(iswin() and {'\\?.dll'} or {'/?.so'})
- local new_cpaths_str = table.concat(new_cpaths, ';')
- eq(new_cpaths_str, eval_lua('package.cpath'):sub(1, #new_cpaths_str))
- end)
- it('puts directories from &runtimepath always at the start', function()
- meths.set_option('runtimepath', 'a,b')
- local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a', 'b'})
- local new_paths_str = table.concat(new_paths, ';')
- eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str))
-
- set_path('path', sl'foo/?.lua;foo/?/init.lua;' .. new_paths_str)
-
- neq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str))
-
- command('set runtimepath+=c')
- new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a', 'b', 'c'})
- new_paths_str = table.concat(new_paths, ';')
- eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str))
- end)
- it('understands uncommon suffixes', function()
- set_path('cpath', './?/foo/bar/baz/x.nlua')
- meths.set_option('runtimepath', 'a')
- local new_paths = get_new_paths({'/?/foo/bar/baz/x.nlua'}, {'a'})
- local new_paths_str = table.concat(new_paths, ';')
- eq(new_paths_str, eval_lua('package.cpath'):sub(1, #new_paths_str))
-
- set_path('cpath', './yyy?zzz/x')
- meths.set_option('runtimepath', 'b')
- new_paths = get_new_paths({'/yyy?zzz/x'}, {'b'})
- new_paths_str = table.concat(new_paths, ';')
- eq(new_paths_str, eval_lua('package.cpath'):sub(1, #new_paths_str))
-
- set_path('cpath', './yyy?zzz/123?ghi/x')
- meths.set_option('runtimepath', 'b')
- new_paths = get_new_paths({'/yyy?zzz/123?ghi/x'}, {'b'})
- new_paths_str = table.concat(new_paths, ';')
- eq(new_paths_str, eval_lua('package.cpath'):sub(1, #new_paths_str))
- end)
- it('preserves empty items', function()
- local many_empty_path = ';;;;;;'
- local many_empty_cpath = ';;;;;;./?.luaso'
- set_path('path', many_empty_path)
- set_path('cpath', many_empty_cpath)
- meths.set_option('runtimepath', 'a')
- local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a'})
- local new_paths_str = table.concat(new_paths, ';')
- eq(new_paths_str .. ';' .. many_empty_path, eval_lua('package.path'))
- local new_cpaths = get_new_paths({'/?.luaso'}, {'a'})
- local new_cpaths_str = table.concat(new_cpaths, ';')
- eq(new_cpaths_str .. ';' .. many_empty_cpath, eval_lua('package.cpath'))
- end)
- it('preserves empty value', function()
- set_path('path', '')
- meths.set_option('runtimepath', 'a')
- local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a'})
- local new_paths_str = table.concat(new_paths, ';')
- eq(new_paths_str .. ';', eval_lua('package.path'))
- end)
- it('purges out all additions if runtimepath is set to empty', function()
- local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'})
- local new_paths_str = table.concat(new_paths, ';')
- local path = eval_lua('package.path')
- eq(new_paths_str, path:sub(1, #new_paths_str))
-
- local new_cpaths = get_new_paths(iswin() and {'\\?.dll'} or {'/?.so'})
- local new_cpaths_str = table.concat(new_cpaths, ';')
- local cpath = eval_lua('package.cpath')
- eq(new_cpaths_str, cpath:sub(1, #new_cpaths_str))
-
- meths.set_option('runtimepath', '')
- eq(path:sub(#new_paths_str + 2, -1), eval_lua('package.path'))
- eq(cpath:sub(#new_cpaths_str + 2, -1), eval_lua('package.cpath'))
- end)
- it('works with paths with escaped commas', function()
- meths.set_option('runtimepath', '\\,')
- local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {','})
- local new_paths_str = table.concat(new_paths, ';')
- eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str))
- end)
- it('ignores paths with semicolons', function()
- meths.set_option('runtimepath', 'foo;bar,\\,')
- local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {','})
- local new_paths_str = table.concat(new_paths, ';')
- eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str))
- end)
-end)
-
describe('os.getenv', function()
it('returns nothing for undefined env var', function()
eq(NIL, funcs.luaeval('os.getenv("XTEST_1")'))
diff --git a/test/functional/lua/treesitter_spec.lua b/test/functional/lua/treesitter_spec.lua
index 3526b64395..9eb5c8b1dd 100644
--- a/test/functional/lua/treesitter_spec.lua
+++ b/test/functional/lua/treesitter_spec.lua
@@ -80,13 +80,6 @@ describe('treesitter API with C parser', function()
eq({1,2,1,12}, exec_lua("return {descendant:range()}"))
eq("(declaration type: (primitive_type) declarator: (init_declarator declarator: (identifier) value: (number_literal)))", exec_lua("return descendant:sexpr()"))
- eq(true, exec_lua("return child == child"))
- -- separate lua object, but represents same node
- eq(true, exec_lua("return child == root:child(0)"))
- eq(false, exec_lua("return child == descendant2"))
- eq(false, exec_lua("return child == nil"))
- eq(false, exec_lua("return child == tree"))
-
feed("2G7|ay")
exec_lua([[
tree2 = parser:parse()
@@ -98,6 +91,21 @@ describe('treesitter API with C parser', function()
eq("<node declaration>", exec_lua("return tostring(descendant2)"))
eq({1,2,1,13}, exec_lua("return {descendant2:range()}"))
+ eq(true, exec_lua("return child == child"))
+ -- separate lua object, but represents same node
+ eq(true, exec_lua("return child == root:child(0)"))
+ eq(false, exec_lua("return child == descendant2"))
+ eq(false, exec_lua("return child == nil"))
+ eq(false, exec_lua("return child == tree"))
+
+ eq("string", exec_lua("return type(child:id())"))
+ eq(true, exec_lua("return child:id() == child:id()"))
+ -- separate lua object, but represents same node
+ eq(true, exec_lua("return child:id() == root:child(0):id()"))
+ eq(false, exec_lua("return child:id() == descendant2:id()"))
+ eq(false, exec_lua("return child:id() == nil"))
+ eq(false, exec_lua("return child:id() == tree"))
+
-- orginal tree did not change
eq({1,2,1,12}, exec_lua("return {descendant:range()}"))
diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua
index 01f0d8a4d7..21c01b3458 100644
--- a/test/functional/ui/cmdline_spec.lua
+++ b/test/functional/ui/cmdline_spec.lua
@@ -3,7 +3,6 @@ local Screen = require('test.functional.ui.screen')
local clear, feed = helpers.clear, helpers.feed
local source = helpers.source
local command = helpers.command
-local feed_command = helpers.feed_command
local function new_screen(opt)
local screen = Screen.new(25, 5)
@@ -843,34 +842,3 @@ describe('cmdline redraw', function()
]], unchanged=true}
end)
end)
-
-describe('cmdline', function()
- before_each(function()
- clear()
- end)
-
- it('prints every executed Ex command if verbose >= 16', function()
- local screen = Screen.new(50, 12)
- screen:attach()
- source([[
- command DoSomething echo 'hello' |set ts=4 |let v = '123' |echo v
- call feedkeys("\r", 't') " for the hit-enter prompt
- set verbose=20
- ]])
- feed_command('DoSomething')
- screen:expect([[
- |
- ~ |
- |
- Executing: DoSomething |
- Executing: echo 'hello' |set ts=4 |let v = '123' ||
- echo v |
- hello |
- Executing: set ts=4 |let v = '123' |echo v |
- Executing: let v = '123' |echo v |
- Executing: echo v |
- 123 |
- Press ENTER or type command to continue^ |
- ]])
- end)
-end)
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 304c5aecb1..4182090732 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -5,20 +5,32 @@ local clear = helpers.clear
local feed = helpers.feed
local insert = helpers.insert
local exec_lua = helpers.exec_lua
+local exec = helpers.exec
local expect_events = helpers.expect_events
+local meths = helpers.meths
-describe('decorations provider', function()
+describe('decorations providers', function()
local screen
before_each(function()
clear()
screen = Screen.new(40, 8)
screen:attach()
- screen:set_default_attr_ids({
- [1] = {bold=true, foreground=Screen.colors.Blue},
- })
+ screen:set_default_attr_ids {
+ [1] = {bold=true, foreground=Screen.colors.Blue};
+ [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red};
+ [3] = {foreground = Screen.colors.Brown};
+ [4] = {foreground = Screen.colors.Blue1};
+ [5] = {foreground = Screen.colors.Magenta};
+ [6] = {bold = true, foreground = Screen.colors.Brown};
+ [7] = {background = Screen.colors.Gray90};
+ [8] = {bold = true, reverse = true};
+ [9] = {reverse = true};
+ [10] = {italic = true, background = Screen.colors.Magenta};
+ [11] = {foreground = Screen.colors.Red, background = tonumber('0x005028')};
+ }
end)
- local mudholland = [[
+ local mulholland = [[
// just to see if there was an accident
// on Mulholland Drive
try_start();
@@ -28,21 +40,21 @@ describe('decorations provider', function()
restore_buffer(&save_buf); ]]
local function setup_provider(code)
- exec_lua ([[
+ return exec_lua ([[
local a = vim.api
- test1 = a.nvim_create_namespace "test1"
+ _G.ns1 = a.nvim_create_namespace "ns1"
]] .. (code or [[
beamtrace = {}
- function on_do(kind, ...)
+ local function on_do(kind, ...)
table.insert(beamtrace, {kind, ...})
end
]]) .. [[
- a.nvim_set_decoration_provider(
- test1, {
+ a.nvim_set_decoration_provider(_G.ns1, {
on_start = on_do; on_buf = on_do;
on_win = on_do; on_line = on_do;
on_end = on_do;
})
+ return _G.ns1
]])
end
@@ -51,8 +63,8 @@ describe('decorations provider', function()
expect_events(expected, actual, "beam trace")
end
- it('leaves a trace', function()
- insert(mudholland)
+ it('leave a trace', function()
+ insert(mulholland)
setup_provider()
@@ -99,11 +111,12 @@ describe('decorations provider', function()
}
end)
- it('single provider', function()
- insert(mudholland)
+ it('can have single provider', function()
+ insert(mulholland)
setup_provider [[
local hl = a.nvim_get_hl_id_by_name "ErrorMsg"
- function do_it(event, ...)
+ local test_ns = a.nvim_create_namespace "mulholland"
+ function on_do(event, ...)
if event == "line" then
local win, buf, line = ...
a.nvim_buf_set_extmark(buf, test_ns, line, line,
@@ -114,5 +127,104 @@ describe('decorations provider', function()
end
end
]]
+
+ screen:expect{grid=[[
+ {2:/}/ just to see if there was an accident |
+ /{2:/} on Mulholland Drive |
+ tr{2:y}_start(); |
+ buf{2:r}ef_T save_buf; |
+ swit{2:c}h_buffer(&save_buf, buf); |
+ posp {2:=} getmark(mark, false); |
+ restor{2:e}_buffer(&save_buf);^ |
+ |
+ ]]}
+ end)
+
+ it('can predefine highlights', function()
+ screen:try_resize(40, 16)
+ insert(mulholland)
+ exec [[
+ 3
+ set ft=c
+ syntax on
+ set number cursorline
+ split
+ ]]
+ local ns1 = setup_provider()
+
+ for k,v in pairs {
+ LineNr = {italic=true, bg="Magenta"};
+ Comment = {fg="#FF0000", bg = 80*256+40};
+ CursorLine = {link="ErrorMsg"};
+ } do meths.set_hl(ns1, k, v) end
+
+ screen:expect{grid=[[
+ {3: 1 }{4:// just to see if there was an accid}|
+ {3: }{4:ent} |
+ {3: 2 }{4:// on Mulholland Drive} |
+ {6: 3 }{7:^try_start(); }|
+ {3: 4 }bufref_T save_buf; |
+ {3: 5 }switch_buffer(&save_buf, buf); |
+ {3: 6 }posp = getmark(mark, {5:false}); |
+ {8:[No Name] [+] }|
+ {3: 2 }{4:// on Mulholland Drive} |
+ {6: 3 }{7:try_start(); }|
+ {3: 4 }bufref_T save_buf; |
+ {3: 5 }switch_buffer(&save_buf, buf); |
+ {3: 6 }posp = getmark(mark, {5:false}); |
+ {3: 7 }restore_buffer(&save_buf); |
+ {9:[No Name] [+] }|
+ |
+ ]]}
+
+ meths.set_hl_ns(ns1)
+ screen:expect{grid=[[
+ {10: 1 }{11:// just to see if there was an accid}|
+ {10: }{11:ent} |
+ {10: 2 }{11:// on Mulholland Drive} |
+ {6: 3 }{2:^try_start(); }|
+ {10: 4 }bufref_T save_buf; |
+ {10: 5 }switch_buffer(&save_buf, buf); |
+ {10: 6 }posp = getmark(mark, {5:false}); |
+ {8:[No Name] [+] }|
+ {10: 2 }{11:// on Mulholland Drive} |
+ {6: 3 }{2:try_start(); }|
+ {10: 4 }bufref_T save_buf; |
+ {10: 5 }switch_buffer(&save_buf, buf); |
+ {10: 6 }posp = getmark(mark, {5:false}); |
+ {10: 7 }restore_buffer(&save_buf); |
+ {9:[No Name] [+] }|
+ |
+ ]]}
+
+ exec_lua [[
+ local a = vim.api
+ local thewin = a.nvim_get_current_win()
+ local ns2 = a.nvim_create_namespace 'ns2'
+ a.nvim_set_decoration_provider (ns2, {
+ on_win = function (_, win, buf)
+ a.nvim_set_hl_ns(win == thewin and _G.ns1 or ns2)
+ end;
+ })
+ ]]
+ screen:expect{grid=[[
+ {10: 1 }{11:// just to see if there was an accid}|
+ {10: }{11:ent} |
+ {10: 2 }{11:// on Mulholland Drive} |
+ {6: 3 }{2:^try_start(); }|
+ {10: 4 }bufref_T save_buf; |
+ {10: 5 }switch_buffer(&save_buf, buf); |
+ {10: 6 }posp = getmark(mark, {5:false}); |
+ {8:[No Name] [+] }|
+ {3: 2 }{4:// on Mulholland Drive} |
+ {6: 3 }{7:try_start(); }|
+ {3: 4 }bufref_T save_buf; |
+ {3: 5 }switch_buffer(&save_buf, buf); |
+ {3: 6 }posp = getmark(mark, {5:false}); |
+ {3: 7 }restore_buffer(&save_buf); |
+ {9:[No Name] [+] }|
+ |
+ ]]}
+
end)
end)
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
index bf979e89f4..8fa9fcc42f 100644
--- a/test/functional/ui/screen.lua
+++ b/test/functional/ui/screen.lua
@@ -1289,7 +1289,7 @@ local function fmt_ext_state(name, state)
for k,v in pairs(state) do
str = (str.." ["..k.."] = {win = {id = "..v.win.id.."}, topline = "
..v.topline..", botline = "..v.botline..", curline = "..v.curline
- ..", curcol = "..v.curcol.."},\n")
+ ..", curcol = "..v.curcol.."};\n")
end
return str .. "}"
else
@@ -1316,7 +1316,7 @@ function Screen:print_snapshot(attrs, ignore)
dict = "{"..self:_pprint_attrs(a).."}"
end
local keyval = (type(i) == "number") and "["..tostring(i).."]" or i
- table.insert(attrstrs, " "..keyval.." = "..dict..",")
+ table.insert(attrstrs, " "..keyval.." = "..dict..";")
end
attrstr = (", attr_ids={\n"..table.concat(attrstrs, "\n").."\n}")
end
diff --git a/test/unit/buffer_spec.lua b/test/unit/buffer_spec.lua
index bf4e5a0e6d..3692e19379 100644
--- a/test/unit/buffer_spec.lua
+++ b/test/unit/buffer_spec.lua
@@ -212,7 +212,7 @@ describe('buffer functions', function()
describe('build_stl_str_hl', function()
local buffer_byte_size = 100
- local STL_MAX_ITEM = 80
+ local STL_INITIAL_ITEMS = 20
local output_buffer = ''
-- This function builds the statusline
@@ -431,31 +431,23 @@ describe('buffer functions', function()
'aaaa%=b%=c%=d%=e%=fg%=hi%=jk%=lmnop%=qrstuv%=wxyz',
'aaaa b c d e fg hi jk lmnop qrstuv wxyz')
- -- maximum stl item testing
- statusline_test('should handle a much larger amount of = than buffer locations', 20,
- ('%='):rep(STL_MAX_ITEM - 1),
- ' ') -- Should be fine, because within limit
- statusline_test('should handle a much larger amount of = than stl max item', 20,
- ('%='):rep(STL_MAX_ITEM + 1),
- ' E541') -- Should show the VIM error
+ -- stl item testing
+ local tabline = ''
+ for i= 1, 1000 do
+ tabline = tabline .. (i % 2 == 0 and '%#TabLineSel#' or '%#TabLineFill#') .. tostring(i % 2)
+ end
+ statusline_test('should handle a large amount of any items', 20,
+ tabline,
+ '<1010101010101010101') -- Should not show any error
+ statusline_test('should handle a larger amount of = than stl initial item', 20,
+ ('%='):rep(STL_INITIAL_ITEMS * 5),
+ ' ') -- Should not show any error
statusline_test('should handle many extra characters', 20,
- 'a' .. ('a'):rep(STL_MAX_ITEM * 4),
- '<aaaaaaaaaaaaaaaaaaa') -- Does not show the error because there are no items
- statusline_test('should handle almost maximum of characters and flags', 20,
- 'a' .. ('%=a'):rep(STL_MAX_ITEM - 1),
- 'a<aaaaaaaaaaaaaaaaaa') -- Should not show the VIM error
- statusline_test('should handle many extra characters and flags', 20,
- 'a' .. ('%=a'):rep(STL_MAX_ITEM),
- 'a<aaaaaaaaaaaaa E541') -- Should show the VIM error
+ 'a' .. ('a'):rep(STL_INITIAL_ITEMS * 5),
+ '<aaaaaaaaaaaaaaaaaaa') -- Does not show any error
statusline_test('should handle many extra characters and flags', 20,
- 'a' .. ('%=a'):rep(STL_MAX_ITEM * 2),
- 'a<aaaaaaaaaaaaa E541') -- Should show the VIM error
- statusline_test('should handle many extra characters and flags with truncation', 20,
- 'aaa%<' .. ('%=a'):rep(STL_MAX_ITEM),
- 'aaa<aaaaaaaaaaa E541') -- Should show the VIM error
- statusline_test('should handle many characters and flags before and after truncation', 20,
- 'a%=a%=a%<' .. ('%=a'):rep(STL_MAX_ITEM),
- 'aaa<aaaaaaaaaaa E541') -- Should show the VIM error
+ 'a' .. ('%=a'):rep(STL_INITIAL_ITEMS * 2),
+ 'a<aaaaaaaaaaaaaaaaaa') -- Should not show any error
-- multi-byte testing
diff --git a/third-party/cmake/GetBinaryDeps.cmake b/third-party/cmake/GetBinaryDeps.cmake
index f262ae7159..982bf62265 100644
--- a/third-party/cmake/GetBinaryDeps.cmake
+++ b/third-party/cmake/GetBinaryDeps.cmake
@@ -39,7 +39,6 @@ function(GetBinaryDep)
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
CONFIGURE_COMMAND ""
BUILD_IN_SOURCE 1
- CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_INSTALL_DIR}/bin
COMMAND "${_gettool_INSTALL_COMMAND}")