aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/news.yml2
-rw-r--r--.github/workflows/test.yml12
-rw-r--r--cmake/InstallHelpers.cmake9
-rw-r--r--runtime/CMakeLists.txt30
-rw-r--r--runtime/doc/api.txt5
-rw-r--r--runtime/doc/news.txt4
-rw-r--r--runtime/doc/syntax.txt4
-rw-r--r--runtime/doc/treesitter.txt46
-rw-r--r--runtime/doc/vim_diff.txt2
-rw-r--r--runtime/lua/vim/filetype.lua2
-rw-r--r--runtime/lua/vim/lsp/semantic_tokens.lua2
-rw-r--r--runtime/lua/vim/treesitter.lua5
-rw-r--r--runtime/lua/vim/treesitter/_meta.lua8
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua240
-rw-r--r--runtime/lua/vim/treesitter/query.lua21
-rw-r--r--runtime/queries/c/injections.scm6
-rw-r--r--runtime/queries/help/injections.scm7
-rw-r--r--runtime/queries/lua/injections.scm16
-rw-r--r--runtime/queries/vim/injections.scm46
-rwxr-xr-xscripts/vim-patch.sh1
-rw-r--r--src/nvim/api/private/helpers.h14
-rw-r--r--src/nvim/buffer_updates.c29
-rw-r--r--src/nvim/eval.c29
-rw-r--r--src/nvim/eval/userfunc.c3
-rw-r--r--src/nvim/eval/vars.c4
-rw-r--r--src/nvim/getchar.c20
-rw-r--r--test/functional/lua/buffer_updates_spec.lua11
-rw-r--r--test/functional/treesitter/utils_spec.lua17
-rw-r--r--test/old/memfile_test.c (renamed from test/old/testdir/samples/memfile_test.c)32
-rw-r--r--test/old/testdir/test_ex_mode.vim36
-rw-r--r--test/old/testdir/test_expr.vim7
-rw-r--r--test/old/testdir/test_filetype.vim2
-rw-r--r--test/old/testdir/test_syntax.vim2
33 files changed, 466 insertions, 208 deletions
diff --git a/.github/workflows/news.yml b/.github/workflows/news.yml
index 11807e9b42..c715bf1031 100644
--- a/.github/workflows/news.yml
+++ b/.github/workflows/news.yml
@@ -1,11 +1,13 @@
name: "news.txt check"
on:
pull_request:
+ types: [opened, synchronize, reopened, ready_for_review]
branches:
- 'master'
jobs:
check:
runs-on: ubuntu-latest
+ if: github.event.pull_request.draft == false
steps:
- uses: actions/checkout@v3
with:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index e6c134b583..22be9bf719 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -241,17 +241,9 @@ jobs:
fi
# Check that all runtime files were installed
- for file in $(git -C runtime ls-files '*.vim' '*.ps' '*.dict' '*.py' '*.tutor'); do
+ for file in $(git -C runtime ls-files '*.vim' '*.ps' '*.dict' '*.py' '*.tutor' '*.awk' '*.sh' '*.bat'); do
if ! test -e "$INSTALL_PREFIX/share/nvim/runtime/$file"; then
- printf "%s%s" 'It appears that %s is not installed.' "$file"
- exit 1
- fi
- done
-
- # Check that some runtime files are installed and are executables
- for file in $(git -C runtime ls-files '*.awk' '*.sh' '*.bat'); do
- if ! test -x "$INSTALL_PREFIX/share/nvim/runtime/$file"; then
- printf "%s%s" 'It appears that %s is not installed or is not executable.' "$file"
+ printf "It appears that %s is not installed." "$file"
exit 1
fi
done
diff --git a/cmake/InstallHelpers.cmake b/cmake/InstallHelpers.cmake
index 3786c4177f..49d8692aae 100644
--- a/cmake/InstallHelpers.cmake
+++ b/cmake/InstallHelpers.cmake
@@ -167,12 +167,3 @@ function(glob_wrapper outvar)
endif()
set(${outvar} ${${outvar}} PARENT_SCOPE)
endfunction()
-
-function(globrecurse_wrapper outvar root)
- if(${CMAKE_VERSION} VERSION_LESS 3.12)
- file(GLOB_RECURSE ${outvar} RELATIVE ${root} ${ARGN})
- else()
- file(GLOB_RECURSE ${outvar} CONFIGURE_DEPENDS RELATIVE ${root} ${ARGN})
- endif()
- set(${outvar} ${${outvar}} PARENT_SCOPE)
-endfunction()
diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt
index 581a4545db..c6447721a0 100644
--- a/runtime/CMakeLists.txt
+++ b/runtime/CMakeLists.txt
@@ -116,23 +116,17 @@ install_helper(
FILES ${CMAKE_CURRENT_SOURCE_DIR}/nvim.png
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps)
-install_helper(
- FILES ${CMAKE_CURRENT_SOURCE_DIR}/neovim.ico
- DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime)
-
-globrecurse_wrapper(RUNTIME_PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR} *.awk *.sh *.bat)
-
-foreach(PROG ${RUNTIME_PROGRAMS})
- get_filename_component(BASEDIR ${PROG} DIRECTORY)
- install_helper(PROGRAMS ${PROG}
- DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/${BASEDIR})
+glob_wrapper(RUNTIME_ROOT_FILES *.vim *.lua *.ico)
+install_helper(FILES ${RUNTIME_ROOT_FILES}
+ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/)
+
+glob_wrapper(RUNTIME_DIRS */)
+foreach(D ${RUNTIME_DIRS})
+ if(IS_DIRECTORY ${D})
+ install_helper(DIRECTORY ${D}
+ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/)
+ endif()
endforeach()
-globrecurse_wrapper(RUNTIME_FILES ${CMAKE_CURRENT_SOURCE_DIR}
- *.vim *.lua *.scm *.dict *.py *.rb *.ps *.spl *.tutor *.tutor.json)
-
-foreach(F ${RUNTIME_FILES})
- get_filename_component(BASEDIR ${F} DIRECTORY)
- install_helper(FILES ${F}
- DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/${BASEDIR})
-endforeach()
+# only foo.sh script in runtime/
+install_helper(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/macros/less.sh DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/macros/)
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 3ca50dda15..0e1cf9ec3e 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -356,6 +356,7 @@ In-process Lua plugins can receive buffer updates in the form of Lua
callbacks. These callbacks are called frequently in various contexts;
|textlock| prevents changing buffer contents and window layout (use
|vim.schedule()| to defer such operations to the main loop instead).
+Moving the cursor is allowed, but it is restored afterwards.
|nvim_buf_attach()| will take keyword args for the callbacks. "on_lines" will
receive parameters ("lines", {buf}, {changedtick}, {firstline}, {lastline},
@@ -451,6 +452,10 @@ Buffer text can be highlighted by typical mechanisms (syntax highlighting,
options from the current window; specify `style=minimal` in |nvim_open_win()|
to disable various visual features such as the 'number' column.
+Other highlight groups specific to floating windows:
+- |hl-FloatBorder| for window's border
+- |hl-FloatTitle| for window's title
+
Currently, floating windows don't support some widgets like scrollbar.
The output of |:mksession| does not include commands for restoring floating
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index f5b9f39d93..04ae9360a0 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -196,6 +196,10 @@ The following new APIs or features were added.
• Added an omnifunc implementation for lua, |vim.lua_omnifunc()|
+• Treesitter injection queries now use the format described at
+ https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection .
+ Support for the previous format will be removed in a future release.
+
==============================================================================
CHANGED FEATURES *news-changes*
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index 68d059be82..b22d673eb9 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -5268,6 +5268,10 @@ NonText '@' at the end of the window, characters from 'showbreak'
Normal Normal text.
*hl-NormalFloat*
NormalFloat Normal text in floating windows.
+ *hl-FloatBorder*
+FloatBorder Border of floating windows.
+ *hl-FloatTitle*
+FloatTitle Title of floating windows.
*hl-NormalNC*
NormalNC Normal text in non-current windows.
*hl-Pmenu*
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 1f78e4d5d9..3b0936941f 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -441,7 +441,53 @@ individual query pattern manually by setting its `"priority"` metadata
attribute: >
(super_important_node) @ImportantHighlight (#set! "priority" 105)
+
+==============================================================================
+TREESITTER LANGUAGE INJECTIONS *treesitter-language-injections*
<
+
+Note the following information is adapted from:
+ https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection
+
+Some source files contain code written in multiple different languages.
+Examples include:
+
+ • HTML files, which can contain JavaScript inside of `<script>` tags and
+ CSS inside of `<style>` tags
+ • ERB files, which contain Ruby inside of `<%` `%>` tags, and HTML outside of
+ those tags
+ • PHP files, which can contain HTML between the `<php` tags
+ • JavaScript files, which contain regular expression syntax within regex
+ literals
+ • Ruby, which can contain snippets of code inside of heredoc literals,
+ where the heredoc delimiter often indicates the language
+ • Lua, which can contain snippets of Vimscript inside |vim.cmd()| calls.
+ • Vimscript, which can contain snippets of Lua inside |:lua-heredoc|
+ blocks.
+
+All of these examples can be modeled in terms of a parent syntax tree and one
+or more injected syntax trees, which reside inside of certain nodes in the
+parent tree. The language injection query allows you to specify these
+“injections” using the following captures:
+
+ • `@injection.content` - indicates that the captured node should have its
+ contents re-parsed using another language.
+ • `@injection.language` - indicates that the captured node’s text may
+ contain the name of a language that should be used to re-parse the
+ `@injection.content`.
+
+The language injection behavior can also be configured by some properties
+associated with patterns:
+
+ • `injection.language` - can be used to hard-code the name of a specific
+ language.
+ • `injection.combined` - indicates that all of the matching nodes in the
+ tree should have their content parsed as one nested document.
+ • `injection.include-children` - indicates that the `@injection.content`
+ node's entire text should be re-parsed, including the text of its child
+ nodes. By default, child nodes' text will be excluded from the injected
+ document.
+
==============================================================================
VIM.TREESITTER *lua-treesitter*
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 5efe094226..2305f101e2 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -243,6 +243,8 @@ Highlight groups:
|highlight-blend| controls blend level for a highlight group
|expr-highlight| highlight groups (prefixed with "Nvim")
|hl-NormalFloat| highlights floating window
+ |hl-FloatBorder| highlights border of a floating window
+ |hl-FloatTitle| highlights title of a floating window
|hl-NormalNC| highlights non-current windows
|hl-MsgArea| highlights messages/cmdline area
|hl-MsgSeparator| highlights separator for scrolled messages
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 65579d3543..8238fec2cc 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -751,6 +751,7 @@ local extension = {
mli = 'ocaml',
ml = 'ocaml',
occ = 'occam',
+ odin = 'odin',
xom = 'omnimark',
xin = 'omnimark',
opam = 'opam',
@@ -1015,6 +1016,7 @@ local extension = {
svh = 'systemverilog',
sv = 'systemverilog',
tak = 'tak',
+ tal = 'tal',
task = 'taskedit',
tm = 'tcl',
tcl = 'tcl',
diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua
index 9eaccd539f..a5e007a011 100644
--- a/runtime/lua/vim/lsp/semantic_tokens.lua
+++ b/runtime/lua/vim/lsp/semantic_tokens.lua
@@ -435,7 +435,7 @@ function STHighlighter:on_win(topline, botline)
token.marked = true
api.nvim_exec_autocmds('LspTokenUpdate', {
- pattern = vim.api.nvim_buf_get_name(self.bufnr),
+ buffer = self.bufnr,
modeline = false,
data = {
token = token,
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index d13824076e..ab9f8968c8 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -191,7 +191,7 @@ end
---
---@return boolean True if the position is in node range
function M.is_in_node_range(node, line, col)
- return M.node_contains(node, { line, col, line, col })
+ return M.node_contains(node, { line, col, line, col + 1 })
end
--- Determines if a node contains a range
@@ -202,7 +202,8 @@ end
---@return boolean True if the {node} contains the {range}
function M.node_contains(node, range)
vim.validate({
- node = { node, 'userdata' },
+ -- allow a table so nodes can be mocked
+ node = { node, { 'userdata', 'table' } },
range = { range, Range.validate, 'integer list with 4 or 6 elements' },
})
return Range.contains({ node:range() }, range)
diff --git a/runtime/lua/vim/treesitter/_meta.lua b/runtime/lua/vim/treesitter/_meta.lua
index 731a5ebf9f..ad0854706b 100644
--- a/runtime/lua/vim/treesitter/_meta.lua
+++ b/runtime/lua/vim/treesitter/_meta.lua
@@ -14,7 +14,7 @@
---@field child_count fun(self: TSNode): integer
---@field named_child_count fun(self: TSNode): integer
---@field child fun(self: TSNode, integer): TSNode
----@field name_child fun(self: TSNode, integer): TSNode
+---@field named_child fun(self: TSNode, integer): TSNode
---@field descendant_for_range fun(self: TSNode, integer, integer, integer, integer): TSNode
---@field named_descendant_for_range fun(self: TSNode, integer, integer, integer, integer): TSNode
---@field parent fun(self: TSNode): TSNode
@@ -43,10 +43,10 @@ function TSNode:_rawquery(query, captures, start, end_) end
function TSNode:_rawquery(query, captures, start, end_) end
---@class TSParser
----@field parse fun(self: TSParser, tree, source: integer|string): TSTree, integer[]
+---@field parse fun(self: TSParser, tree, source: integer|string): TSTree, Range4[]
---@field reset fun(self: TSParser)
----@field included_ranges fun(self: TSParser): integer[]
----@field set_included_ranges fun(self: TSParser, ranges: integer[][])
+---@field included_ranges fun(self: TSParser): Range4[]
+---@field set_included_ranges fun(self: TSParser, ranges: Range6[])
---@field set_timeout fun(self: TSParser, timeout: integer)
---@field timeout fun(self: TSParser): integer
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index b8b0dd867e..fbc602486b 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -399,6 +399,169 @@ local function get_range_from_metadata(node, id, metadata)
return { node:range() }
end
+---@private
+--- TODO(lewis6991): cleanup of the node_range interface
+---@param node TSNode
+---@param id integer
+---@param metadata TSMetadata
+---@return Range4[]
+local function get_node_ranges(node, id, metadata, include_children)
+ local range = get_range_from_metadata(node, id, metadata)
+
+ if include_children then
+ return { range }
+ end
+
+ local ranges = {} ---@type Range4[]
+
+ local srow, scol, erow, ecol = range[1], range[2], range[3], range[4]
+
+ for i = 0, node:named_child_count() - 1 do
+ local child = node:named_child(i)
+ local child_srow, child_scol, child_erow, child_ecol = child:range()
+ if child_srow > srow or child_scol > scol then
+ table.insert(ranges, { srow, scol, child_srow, child_scol })
+ end
+ srow = child_erow
+ scol = child_ecol
+ end
+
+ if erow > srow or ecol > scol then
+ table.insert(ranges, { srow, scol, erow, ecol })
+ end
+
+ return ranges
+end
+
+---@alias TSInjection table<string,table<integer,table>>
+
+---@private
+---@param t table<integer,TSInjection>
+---@param tree_index integer
+---@param pattern integer
+---@param lang string
+---@param combined boolean
+---@param ranges Range4[]
+local function add_injection(t, tree_index, pattern, lang, combined, ranges)
+ assert(type(lang) == 'string')
+
+ -- Each tree index should be isolated from the other nodes.
+ if not t[tree_index] then
+ t[tree_index] = {}
+ end
+
+ if not t[tree_index][lang] then
+ t[tree_index][lang] = {}
+ end
+
+ -- Key this by pattern. If combined is set to true all captures of this pattern
+ -- will be parsed by treesitter as the same "source".
+ -- If combined is false, each "region" will be parsed as a single source.
+ if not t[tree_index][lang][pattern] then
+ t[tree_index][lang][pattern] = { combined = combined, regions = {} }
+ end
+
+ table.insert(t[tree_index][lang][pattern].regions, ranges)
+end
+
+---@private
+---Get node text
+---
+---Note: `query.get_node_text` returns string|string[]|nil so use this simple alias function
+---to annotate it returns string.
+---
+---TODO(lewis6991): use [at]overload annotations on `query.get_node_text`
+---@param node TSNode
+---@param source integer|string
+---@param metadata table
+---@return string
+local function get_node_text(node, source, metadata)
+ return query.get_node_text(node, source, { metadata = metadata }) --[[@as string]]
+end
+
+---@private
+--- Extract injections according to:
+--- https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection
+---@param match table<integer,TSNode>
+---@param metadata table
+---@return string, boolean, Range4[]
+function LanguageTree:_get_injection(match, metadata)
+ local ranges = {} ---@type Range4[]
+ local combined = metadata['injection.combined'] ~= nil
+ local lang = metadata['injection.language'] ---@type string
+ local include_children = metadata['injection.include-children'] ~= nil
+
+ for id, node in pairs(match) do
+ local name = self._injection_query.captures[id]
+
+ -- Lang should override any other language tag
+ if name == 'injection.language' then
+ lang = get_node_text(node, self._source, metadata[id])
+ elseif name == 'injection.content' then
+ ranges = get_node_ranges(node, id, metadata, include_children)
+ end
+ end
+
+ return lang, combined, ranges
+end
+
+---@private
+---@param match table<integer,TSNode>
+---@param metadata table
+---@return string, boolean, Range4[]
+function LanguageTree:_get_injection_deprecated(match, metadata)
+ local lang = nil ---@type string
+ local ranges = {} ---@type Range4[]
+ local combined = metadata.combined ~= nil
+
+ -- Directives can configure how injections are captured as well as actual node captures.
+ -- This allows more advanced processing for determining ranges and language resolution.
+ if metadata.content then
+ local content = metadata.content ---@type any
+
+ -- Allow for captured nodes to be used
+ if type(content) == 'number' then
+ content = { match[content]:range() }
+ end
+
+ if type(content) == 'table' and #content >= 4 then
+ vim.list_extend(ranges, content)
+ end
+ end
+
+ if metadata.language then
+ lang = metadata.language ---@type string
+ end
+
+ -- You can specify the content and language together
+ -- using a tag with the language, for example
+ -- @javascript
+ for id, node in pairs(match) do
+ local name = self._injection_query.captures[id]
+
+ -- Lang should override any other language tag
+ if name == 'language' and not lang then
+ lang = get_node_text(node, self._source, metadata[id])
+ elseif name == 'combined' then
+ combined = true
+ elseif name == 'content' and #ranges == 0 then
+ table.insert(ranges, get_range_from_metadata(node, id, metadata))
+ -- Ignore any tags that start with "_"
+ -- Allows for other tags to be used in matches
+ elseif string.sub(name, 1, 1) ~= '_' then
+ if not lang then
+ lang = name
+ end
+
+ if #ranges == 0 then
+ table.insert(ranges, get_range_from_metadata(node, id, metadata))
+ end
+ end
+ end
+
+ return lang, combined, ranges
+end
+
--- Gets language injection points by language.
---
--- This is where most of the injection processing occurs.
@@ -406,13 +569,13 @@ end
--- TODO: Allow for an offset predicate to tailor the injection range
--- instead of using the entire nodes range.
---@private
----@return table<string, integer[][]>
+---@return table<string, Range4[][]>
function LanguageTree:_get_injections()
if not self._injection_query then
return {}
end
- ---@type table<integer,table<string,table<integer,table>>>
+ ---@type table<integer,TSInjection>
local injections = {}
for tree_index, tree in ipairs(self._trees) do
@@ -422,75 +585,12 @@ function LanguageTree:_get_injections()
for pattern, match, metadata in
self._injection_query:iter_matches(root_node, self._source, start_line, end_line + 1)
do
- local lang = nil ---@type string
- local ranges = {} ---@type Range4[]
- local combined = metadata.combined ---@type boolean
-
- -- Directives can configure how injections are captured as well as actual node captures.
- -- This allows more advanced processing for determining ranges and language resolution.
- if metadata.content then
- local content = metadata.content ---@type any
-
- -- Allow for captured nodes to be used
- if type(content) == 'number' then
- content = { match[content]:range() }
- end
-
- if type(content) == 'table' and #content >= 4 then
- vim.list_extend(ranges, content)
- end
- end
-
- if metadata.language then
- lang = metadata.language ---@type string
- end
-
- -- You can specify the content and language together
- -- using a tag with the language, for example
- -- @javascript
- for id, node in pairs(match) do
- local name = self._injection_query.captures[id]
-
- -- Lang should override any other language tag
- if name == 'language' and not lang then
- ---@diagnostic disable-next-line
- lang = query.get_node_text(node, self._source, { metadata = metadata[id] })
- elseif name == 'combined' then
- combined = true
- elseif name == 'content' and #ranges == 0 then
- table.insert(ranges, get_range_from_metadata(node, id, metadata))
- -- Ignore any tags that start with "_"
- -- Allows for other tags to be used in matches
- elseif string.sub(name, 1, 1) ~= '_' then
- if not lang then
- lang = name
- end
-
- if #ranges == 0 then
- table.insert(ranges, get_range_from_metadata(node, id, metadata))
- end
- end
+ local lang, combined, ranges = self:_get_injection(match, metadata)
+ if not lang then
+ -- TODO(lewis6991): remove after 0.9 (#20434)
+ lang, combined, ranges = self:_get_injection_deprecated(match, metadata)
end
-
- assert(type(lang) == 'string')
-
- -- Each tree index should be isolated from the other nodes.
- if not injections[tree_index] then
- injections[tree_index] = {}
- end
-
- if not injections[tree_index][lang] then
- injections[tree_index][lang] = {}
- end
-
- -- Key this by pattern. If combined is set to true all captures of this pattern
- -- will be parsed by treesitter as the same "source".
- -- If combined is false, each "region" will be parsed as a single source.
- if not injections[tree_index][lang][pattern] then
- injections[tree_index][lang][pattern] = { combined = combined, regions = {} }
- end
-
- table.insert(injections[tree_index][lang][pattern].regions, ranges)
+ add_injection(injections, tree_index, pattern, lang, combined, ranges)
end
end
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 22f706585e..59894cc7f5 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -407,7 +407,7 @@ predicate_handlers['vim-match?'] = predicate_handlers['match?']
---@field [string] integer|string
---@field range Range4
----@alias TSDirective fun(match: TSMatch, _, _, predicate: any[], metadata: TSMetadata)
+---@alias TSDirective fun(match: TSMatch, _, _, predicate: (string|integer)[], metadata: TSMetadata)
-- Predicate handler receive the following arguments
-- (match, pattern, bufnr, predicate)
@@ -419,24 +419,17 @@ predicate_handlers['vim-match?'] = predicate_handlers['match?']
---@type table<string,TSDirective>
local directive_handlers = {
['set!'] = function(_, _, _, pred, metadata)
- if #pred == 4 then
- -- (#set! @capture "key" "value")
- ---@diagnostic disable-next-line:no-unknown
- local _, capture_id, key, value = unpack(pred)
- ---@cast value integer|string
- ---@cast capture_id integer
- ---@cast key string
+ if #pred >= 3 and type(pred[2]) == 'number' then
+ -- (#set! @capture key value)
+ local capture_id, key, value = pred[2], pred[3], pred[4]
if not metadata[capture_id] then
metadata[capture_id] = {}
end
metadata[capture_id][key] = value
else
- ---@diagnostic disable-next-line:no-unknown
- local _, key, value = unpack(pred)
- ---@cast value integer|string
- ---@cast key string
- -- (#set! "key" "value")
- metadata[key] = value
+ -- (#set! key value)
+ local key, value = pred[2], pred[3]
+ metadata[key] = value or true
end
end,
-- Shifts the range of a node.
diff --git a/runtime/queries/c/injections.scm b/runtime/queries/c/injections.scm
index 7e9e73449d..84ae33683e 100644
--- a/runtime/queries/c/injections.scm
+++ b/runtime/queries/c/injections.scm
@@ -1,3 +1,5 @@
-(preproc_arg) @c
+((preproc_arg) @injection.content
+ (#set! injection.language "c"))
-; (comment) @comment
+; ((comment) @injection.content
+; (#set! injection.language "comment"))
diff --git a/runtime/queries/help/injections.scm b/runtime/queries/help/injections.scm
index 09bbe44e84..260a05d863 100644
--- a/runtime/queries/help/injections.scm
+++ b/runtime/queries/help/injections.scm
@@ -1,3 +1,4 @@
-(codeblock
- (language) @language
- (code) @content)
+((codeblock
+ (language) @injection.language
+ (code) @injection.content)
+ (#set! injection.include-children))
diff --git a/runtime/queries/lua/injections.scm b/runtime/queries/lua/injections.scm
index 69acbbbe9f..10eb4c4054 100644
--- a/runtime/queries/lua/injections.scm
+++ b/runtime/queries/lua/injections.scm
@@ -3,20 +3,26 @@
(identifier) @_cdef_identifier
(_ _ (identifier) @_cdef_identifier)
]
- arguments: (arguments (string content: _ @c)))
+ arguments: (arguments (string content: _ @injection.content)))
+ (#set! injection.language "c")
(#eq? @_cdef_identifier "cdef"))
((function_call
name: (_) @_vimcmd_identifier
- arguments: (arguments (string content: _ @vim)))
+ arguments: (arguments (string content: _ @injection.content)))
+ (#set! injection.language "vim")
(#any-of? @_vimcmd_identifier "vim.cmd" "vim.api.nvim_command" "vim.api.nvim_exec" "vim.api.nvim_cmd"))
((function_call
name: (_) @_vimcmd_identifier
- arguments: (arguments (string content: _ @query) .))
+ arguments: (arguments (string content: _ @injection.content) .))
+ (#set! injection.language "query")
(#eq? @_vimcmd_identifier "vim.treesitter.query.set_query"))
; ;; highlight string as query if starts with `;; query`
-; ((string ("string_content") @query) (#lua-match? @query "^%s*;+%s?query"))
+; ((string ("string_content") @injection.content)
+; (#set! injection.language "query")
+; (#lua-match? @injection.content "^%s*;+%s?query"))
-; (comment) @comment
+; ((comment) @injection.content
+; (#set! injection.language "comment"))
diff --git a/runtime/queries/vim/injections.scm b/runtime/queries/vim/injections.scm
index b53643dc1a..50f0190112 100644
--- a/runtime/queries/vim/injections.scm
+++ b/runtime/queries/vim/injections.scm
@@ -1,18 +1,33 @@
-(lua_statement (script (body) @lua))
-(lua_statement (chunk) @lua)
-(ruby_statement (script (body) @ruby))
-(ruby_statement (chunk) @ruby)
-(python_statement (script (body) @python))
-(python_statement (chunk) @python)
+((lua_statement (script (body) @injection.content))
+ (#set! injection.language "lua"))
+
+((lua_statement (chunk) @injection.content)
+ (#set! injection.language "lua"))
+
+((ruby_statement (script (body) @injection.content))
+ (#set! injection.language "ruby"))
+
+((ruby_statement (chunk) @injection.content)
+ (#set! injection.language "ruby"))
+
+((python_statement (script (body) @injection.content))
+ (#set! injection.language "python"))
+
+((python_statement (chunk) @injection.content)
+ (#set! injection.language "python"))
+
;; If we support perl at some point...
-;; (perl_statement (script (body) @perl))
-;; (perl_statement (chunk) @perl)
+;; ((perl_statement (script (body) @injection.content))
+;; (#set! injection.language "perl"))
+;; ((perl_statement (chunk) @injection.content)
+;; (#set! injection.language "perl"))
-(autocmd_statement (pattern) @regex)
+((autocmd_statement (pattern) @injection.content)
+ (#set! injection.language "regex"))
((set_item
option: (option_name) @_option
- value: (set_value) @vim)
+ value: (set_value) @injection.content)
(#any-of? @_option
"includeexpr" "inex"
"printexpr" "pexpr"
@@ -22,7 +37,12 @@
"foldexpr" "fde"
"diffexpr" "dex"
"patchexpr" "pex"
- "charconvert" "ccv"))
+ "charconvert" "ccv")
+ (#set! injection.language "vim"))
+
+
+; ((comment) @injection.content
+; (#set! injection.language "comment"))
-; (comment) @comment
-; (line_continuation_comment) @comment
+; ((line_continuation_comment) @injection.content
+; (#set! injection.language "comment"))
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 06ddf0f3b8..20e337afcb 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -598,6 +598,7 @@ _set_missing_vimpatches() {
# Massage arguments for git-log.
declare -A git_log_replacements=(
[^\(.*/\)?src/nvim/\(.*\)]="\${BASH_REMATCH[1]}src/\${BASH_REMATCH[2]}"
+ [^\(.*/\)?test/old/\(.*\)]="\${BASH_REMATCH[1]}src/\${BASH_REMATCH[2]}"
[^\(.*/\)?\.vim-src/\(.*\)]="\${BASH_REMATCH[2]}"
)
local i j
diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h
index b70452d7cb..1b82aeac34 100644
--- a/src/nvim/api/private/helpers.h
+++ b/src/nvim/api/private/helpers.h
@@ -155,8 +155,18 @@ typedef struct {
msglist_T *private_msg_list; \
msg_list = &private_msg_list; \
private_msg_list = NULL; \
- code \
- msg_list = saved_msg_list; /* Restore the exception context. */ \
+ code; \
+ msg_list = saved_msg_list; /* Restore the exception context. */ \
+ } while (0)
+
+// Execute code with cursor position saved and restored and textlock active.
+#define TEXTLOCK_WRAP(code) \
+ do { \
+ const pos_T save_cursor = curwin->w_cursor; \
+ textlock++; \
+ code; \
+ textlock--; \
+ curwin->w_cursor = save_cursor; \
} while (0)
// Useful macro for executing some `code` for each item in an array.
diff --git a/src/nvim/buffer_updates.c b/src/nvim/buffer_updates.c
index 075ac2adbf..9543731c9b 100644
--- a/src/nvim/buffer_updates.c
+++ b/src/nvim/buffer_updates.c
@@ -188,9 +188,9 @@ void buf_updates_unload(buf_T *buf, bool can_reload)
// the first argument is always the buffer handle
args.items[0] = BUFFER_OBJ(buf->handle);
- textlock++;
- nlua_call_ref(thecb, keep ? "reload" : "detach", args, false, NULL);
- textlock--;
+ TEXTLOCK_WRAP({
+ nlua_call_ref(thecb, keep ? "reload" : "detach", args, false, NULL);
+ });
}
if (keep) {
@@ -305,9 +305,11 @@ void buf_updates_send_changes(buf_T *buf, linenr_T firstline, int64_t num_added,
args.items[6] = INTEGER_OBJ((Integer)deleted_codepoints);
args.items[7] = INTEGER_OBJ((Integer)deleted_codeunits);
}
- textlock++;
- Object res = nlua_call_ref(cb.on_lines, "lines", args, false, NULL);
- textlock--;
+
+ Object res;
+ TEXTLOCK_WRAP({
+ res = nlua_call_ref(cb.on_lines, "lines", args, false, NULL);
+ });
if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
buffer_update_callbacks_free(cb);
@@ -354,9 +356,10 @@ void buf_updates_send_splice(buf_T *buf, int start_row, colnr_T start_col, bcoun
ADD_C(args, INTEGER_OBJ(new_col));
ADD_C(args, INTEGER_OBJ(new_byte));
- textlock++;
- Object res = nlua_call_ref(cb.on_bytes, "bytes", args, false, NULL);
- textlock--;
+ Object res;
+ TEXTLOCK_WRAP({
+ res = nlua_call_ref(cb.on_bytes, "bytes", args, false, NULL);
+ });
if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
buffer_update_callbacks_free(cb);
@@ -389,10 +392,10 @@ void buf_updates_changedtick(buf_T *buf)
// next argument is b:changedtick
ADD_C(args, INTEGER_OBJ(buf_get_changedtick(buf)));
- textlock++;
- Object res = nlua_call_ref(cb.on_changedtick, "changedtick",
- args, false, NULL);
- textlock--;
+ Object res;
+ TEXTLOCK_WRAP({
+ res = nlua_call_ref(cb.on_changedtick, "changedtick", args, false, NULL);
+ });
if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
buffer_update_callbacks_free(cb);
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index cbad5d04ff..9b42375120 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -2906,6 +2906,12 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
case '8':
case '9':
ret = get_number_tv(arg, rettv, evaluate, want_string);
+
+ // Apply prefixed "-" and "+" now. Matters especially when
+ // "->" follows.
+ if (ret == OK && evaluate && end_leader > start_leader) {
+ ret = eval7_leader(rettv, true, start_leader, &end_leader);
+ }
break;
// String constant: "string".
@@ -3011,13 +3017,12 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
// Handle following '[', '(' and '.' for expr[expr], expr.name,
// expr(expr), expr->name(expr)
if (ret == OK) {
- ret = handle_subscript((const char **)arg, rettv, evaluate, true,
- (char *)start_leader, &end_leader);
+ ret = handle_subscript((const char **)arg, rettv, evaluate, true);
}
// Apply logical NOT and unary '-', from right to left, ignore '+'.
if (ret == OK && evaluate && end_leader > start_leader) {
- ret = eval7_leader(rettv, (char *)start_leader, &end_leader);
+ ret = eval7_leader(rettv, false, start_leader, &end_leader);
}
recurse--;
@@ -3027,9 +3032,11 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
/// Apply the leading "!" and "-" before an eval7 expression to "rettv".
/// Adjusts "end_leaderp" until it is at "start_leader".
///
+/// @param numeric_only if true only handle "+" and "-".
+///
/// @return OK on success, FAIL on failure.
-static int eval7_leader(typval_T *const rettv, const char *const start_leader,
- const char **const end_leaderp)
+static int eval7_leader(typval_T *const rettv, const bool numeric_only,
+ const char *const start_leader, const char **const end_leaderp)
FUNC_ATTR_NONNULL_ALL
{
const char *end_leader = (char *)(*end_leaderp);
@@ -3050,6 +3057,10 @@ static int eval7_leader(typval_T *const rettv, const char *const start_leader,
while (end_leader > start_leader) {
end_leader--;
if (*end_leader == '!') {
+ if (numeric_only) {
+ end_leader++;
+ break;
+ }
if (rettv->v_type == VAR_FLOAT) {
f = !(bool)f;
} else {
@@ -6899,8 +6910,7 @@ int check_luafunc_name(const char *const str, const bool paren)
/// @param verbose give error messages
/// @param start_leader start of '!' and '-' prefixes
/// @param end_leaderp end of '!' and '-' prefixes
-int handle_subscript(const char **const arg, typval_T *rettv, int evaluate, int verbose,
- const char *const start_leader, const char **const end_leaderp)
+int handle_subscript(const char **const arg, typval_T *rettv, int evaluate, int verbose)
{
int ret = OK;
dict_T *selfdict = NULL;
@@ -6944,11 +6954,6 @@ int handle_subscript(const char **const arg, typval_T *rettv, int evaluate, int
tv_dict_unref(selfdict);
selfdict = NULL;
} else if (**arg == '-') {
- // Expression "-1.0->method()" applies the leader "-" before
- // applying ->.
- if (evaluate && *end_leaderp > start_leader) {
- ret = eval7_leader(rettv, (char *)start_leader, end_leaderp);
- }
if (ret == OK) {
if ((*arg)[2] == '{') {
// expr->{lambda}()
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index 3c4cc34464..13779f4173 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -3075,8 +3075,7 @@ void ex_call(exarg_T *eap)
}
// Handle a function returning a Funcref, Dictionary or List.
- if (handle_subscript((const char **)&arg, &rettv, true, true,
- (const char *)name, (const char **)&name)
+ if (handle_subscript((const char **)&arg, &rettv, true, true)
== FAIL) {
failed = true;
break;
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c
index d80bdc70f6..ed2453bd59 100644
--- a/src/nvim/eval/vars.c
+++ b/src/nvim/eval/vars.c
@@ -508,7 +508,7 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first)
} else {
// handle d.key, l[idx], f(expr)
const char *const arg_subsc = arg;
- if (handle_subscript(&arg, &tv, true, true, name, &name) == FAIL) {
+ if (handle_subscript(&arg, &tv, true, true) == FAIL) {
error = true;
} else {
if (arg == arg_subsc && len == 2 && name[1] == ':') {
@@ -1715,7 +1715,7 @@ bool var_exists(const char *var)
n = get_var_tv(name, len, &tv, NULL, false, true) == OK;
if (n) {
// Handle d.key, l[idx], f(expr).
- n = handle_subscript(&var, &tv, true, false, name, &name) == OK;
+ n = handle_subscript(&var, &tv, true, false) == OK;
if (n) {
tv_clear(&tv);
}
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 183fd5e19f..ea541dbca4 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -2345,7 +2345,7 @@ void check_end_reg_executing(bool advance)
/// K_SPECIAL may be escaped, need to get two more bytes then.
static int vgetorpeek(bool advance)
{
- int c, c1;
+ int c;
bool timedout = false; // waited for more than 'timeoutlen'
// for mapping to complete or
// 'ttimeoutlen' for complete key code
@@ -2639,7 +2639,7 @@ static int vgetorpeek(bool advance)
// input from the user), show the partially matched characters
// to the user with showcmd.
int showcmd_idx = 0;
- c1 = 0;
+ bool showing_partial = false;
if (typebuf.tb_len > 0 && advance && !exmode_active) {
if (((State & (MODE_NORMAL | MODE_INSERT)) || State == MODE_LANGMAP)
&& State != MODE_HITRETURN) {
@@ -2648,7 +2648,7 @@ static int vgetorpeek(bool advance)
&& ptr2cells((char *)typebuf.tb_buf + typebuf.tb_off + typebuf.tb_len - 1) == 1) {
edit_putchar(typebuf.tb_buf[typebuf.tb_off + typebuf.tb_len - 1], false);
setcursor(); // put cursor back where it belongs
- c1 = 1;
+ showing_partial = true;
}
// need to use the col and row from above here
old_wcol = curwin->w_wcol;
@@ -2666,12 +2666,15 @@ static int vgetorpeek(bool advance)
curwin->w_wrow = old_wrow;
}
- // this looks nice when typing a dead character map
- if ((State & MODE_CMDLINE) && cmdline_star == 0) {
+ // This looks nice when typing a dead character map.
+ // There is no actual command line for get_number().
+ if ((State & MODE_CMDLINE)
+ && get_cmdline_info()->cmdbuff != NULL
+ && cmdline_star == 0) {
char *p = (char *)typebuf.tb_buf + typebuf.tb_off + typebuf.tb_len - 1;
if (ptr2cells(p) == 1 && (uint8_t)(*p) < 128) {
putcmdline(*p, false);
- c1 = 1;
+ showing_partial = true;
}
}
}
@@ -2704,11 +2707,12 @@ static int vgetorpeek(bool advance)
if (showcmd_idx != 0) {
pop_showcmd();
}
- if (c1 == 1) {
+ if (showing_partial == 1) {
if (State & MODE_INSERT) {
edit_unputchar();
}
- if (State & MODE_CMDLINE) {
+ if ((State & MODE_CMDLINE)
+ && get_cmdline_info()->cmdbuff != NULL) {
unputcmdline();
} else {
setcursor(); // put cursor back where it belongs
diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua
index 2fd44b8b5f..b1b39501f7 100644
--- a/test/functional/lua/buffer_updates_spec.lua
+++ b/test/functional/lua/buffer_updates_spec.lua
@@ -317,7 +317,18 @@ describe('lua buffer event callbacks: on_lines', function()
feed('1G0')
feed('P')
eq(meths.get_var('linesev'), { "lines", 1, 6, 0, 3, 3, 9 })
+ end)
+ it('calling nvim_buf_call() from callback does not cause Normal mode CTRL-A to misbehave #16729', function()
+ exec_lua([[
+ vim.api.nvim_buf_attach(0, false, {
+ on_lines = function(...)
+ vim.api.nvim_buf_call(0, function() end)
+ end,
+ })
+ ]])
+ feed('itest123<Esc><C-A>')
+ eq('test124', meths.get_current_line())
end)
end)
diff --git a/test/functional/treesitter/utils_spec.lua b/test/functional/treesitter/utils_spec.lua
index 7f5a864c3d..9c07959098 100644
--- a/test/functional/treesitter/utils_spec.lua
+++ b/test/functional/treesitter/utils_spec.lua
@@ -28,4 +28,21 @@ describe('treesitter utils', function()
eq(true, exec_lua('return vim.treesitter.is_ancestor(ancestor, child)'))
eq(false, exec_lua('return vim.treesitter.is_ancestor(child, ancestor)'))
end)
+
+ it('can detect if a position is contained in a node', function()
+ exec_lua([[
+ node = {
+ range = function()
+ return 0, 4, 0, 8
+ end,
+ }
+ ]])
+
+ eq(false, exec_lua('return vim.treesitter.is_in_node_range(node, 0, 3)'))
+ for i = 4, 7 do
+ eq(true, exec_lua('return vim.treesitter.is_in_node_range(node, 0, ...)', i))
+ end
+ -- End column exclusive
+ eq(false, exec_lua('return vim.treesitter.is_in_node_range(node, 0, 8)'))
+ end)
end)
diff --git a/test/old/testdir/samples/memfile_test.c b/test/old/memfile_test.c
index 73f67fb250..41316bcc2d 100644
--- a/test/old/testdir/samples/memfile_test.c
+++ b/test/old/memfile_test.c
@@ -1,8 +1,6 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-// uncrustify:off
-
/* vi:set ts=8 sts=4 sw=4 noet:
*
* VIM - Vi IMproved by Bram Moolenaar
@@ -20,11 +18,11 @@
#undef NDEBUG
#include <assert.h>
-/* Must include main.c because it contains much more than just main() */
+// Must include main.c because it contains much more than just main()
#define NO_VIM_MAIN
#include "main.c"
-/* This file has to be included because the tested functions are static */
+// This file has to be included because the tested functions are static
#include "memfile.c"
#define index_to_key(i) ((i) ^ 15167)
@@ -39,26 +37,26 @@ test_mf_hash(void)
mf_hashtab_T ht;
mf_hashitem_T *item;
blocknr_T key;
- size_t i;
- size_t num_buckets;
+ long_u i;
+ long_u num_buckets;
mf_hash_init(&ht);
- /* insert some items and check invariants */
+ // insert some items and check invariants
for (i = 0; i < TEST_COUNT; i++)
{
assert(ht.mht_count == i);
- /* check that number of buckets is a power of 2 */
+ // check that number of buckets is a power of 2
num_buckets = ht.mht_mask + 1;
assert(num_buckets > 0 && (num_buckets & (num_buckets - 1)) == 0);
- /* check load factor */
+ // check load factor
assert(ht.mht_count <= (num_buckets << MHT_LOG_LOAD_FACTOR));
if (i < (MHT_INIT_SIZE << MHT_LOG_LOAD_FACTOR))
{
- /* first expansion shouldn't have occurred yet */
+ // first expansion shouldn't have occurred yet
assert(num_buckets == MHT_INIT_SIZE);
assert(ht.mht_buckets == ht.mht_small_buckets);
}
@@ -71,8 +69,8 @@ test_mf_hash(void)
key = index_to_key(i);
assert(mf_hash_find(&ht, key) == NULL);
- /* allocate and add new item */
- item = (mf_hashitem_T *)lalloc_clear(sizeof(*item), FALSE);
+ // allocate and add new item
+ item = LALLOC_CLEAR_ONE(mf_hashitem_T);
assert(item != NULL);
item->mhi_key = key;
mf_hash_add_item(&ht, item);
@@ -81,13 +79,13 @@ test_mf_hash(void)
if (ht.mht_mask + 1 != num_buckets)
{
- /* hash table was expanded */
+ // hash table was expanded
assert(ht.mht_mask + 1 == num_buckets * MHT_GROWTH_FACTOR);
assert(i + 1 == (num_buckets << MHT_LOG_LOAD_FACTOR));
}
}
- /* check presence of inserted items */
+ // check presence of inserted items
for (i = 0; i < TEST_COUNT; i++)
{
key = index_to_key(i);
@@ -96,7 +94,7 @@ test_mf_hash(void)
assert(item->mhi_key == key);
}
- /* delete some items */
+ // delete some items
for (i = 0; i < TEST_COUNT; i++)
{
if (i % 100 < 70)
@@ -119,7 +117,7 @@ test_mf_hash(void)
}
}
- /* check again */
+ // check again
for (i = 0; i < TEST_COUNT; i++)
{
key = index_to_key(i);
@@ -136,7 +134,7 @@ test_mf_hash(void)
}
}
- /* free hash table and all remaining items */
+ // free hash table and all remaining items
mf_hash_free_all(&ht);
}
diff --git a/test/old/testdir/test_ex_mode.vim b/test/old/testdir/test_ex_mode.vim
index 93100732ed..b30dce8630 100644
--- a/test/old/testdir/test_ex_mode.vim
+++ b/test/old/testdir/test_ex_mode.vim
@@ -123,6 +123,42 @@ func Test_open_command()
close!
endfunc
+func Test_open_command_flush_line()
+ throw 'Skipped: Nvim does not have :open'
+ " this was accessing freed memory: the regexp match uses a pointer to the
+ " current line which becomes invalid when searching for the ') mark.
+ new
+ call setline(1, ['one', 'two. three'])
+ s/one/ONE
+ try
+ open /\%')/
+ catch /E479/
+ endtry
+ bwipe!
+endfunc
+
+" FIXME: this doesn't fail without the fix but hangs
+func Skip_Test_open_command_state()
+ " Tricky script that failed because State was not set properly
+ let lines =<< trim END
+ !ls ƒ
+ 0scìi
+ so! Xsourced
+ set t_û0=0
+ v/-/o
+ END
+ call writefile(lines, 'XopenScript', '')
+
+ let sourced = ["!f\u0083\x02\<Esc>z=0"]
+ call writefile(sourced, 'Xsourced', 'b')
+
+ CheckRunVimInTerminal
+ let buf = RunVimInTerminal('-u NONE -i NONE -n -m -X -Z -e -s -S XopenScript -c qa!', #{rows: 6, wait_for_ruler: 0, no_clean: 1})
+ sleep 3
+
+ call StopVimInTerminal(buf)
+endfunc
+
" Test for :g/pat/visual to run vi commands in Ex mode
" This used to hang Vim before 8.2.0274.
func Test_Ex_global()
diff --git a/test/old/testdir/test_expr.vim b/test/old/testdir/test_expr.vim
index 47f7f5eb0e..292a504df9 100644
--- a/test/old/testdir/test_expr.vim
+++ b/test/old/testdir/test_expr.vim
@@ -111,6 +111,13 @@ func Test_special_char()
call assert_fails('echo "\<C-">')
endfunc
+func Test_method_with_prefix()
+ call assert_equal(1, !range(5)->empty())
+ call assert_equal([0, 1, 2], --3->range())
+ call assert_equal(0, !-3)
+ call assert_equal(1, !+-+0)
+endfunc
+
func Test_option_value()
" boolean
set bri
diff --git a/test/old/testdir/test_filetype.vim b/test/old/testdir/test_filetype.vim
index eb00cb98ca..cb16200afc 100644
--- a/test/old/testdir/test_filetype.vim
+++ b/test/old/testdir/test_filetype.vim
@@ -414,6 +414,7 @@ let s:filename_checks = {
\ 'ocaml': ['file.ml', 'file.mli', 'file.mll', 'file.mly', '.ocamlinit', 'file.mlt', 'file.mlp', 'file.mlip', 'file.mli.cppo', 'file.ml.cppo'],
\ 'occam': ['file.occ'],
\ 'octave': ['octaverc', '.octaverc', 'octave.conf'],
+ \ 'odin': ['file.odin'],
\ 'omnimark': ['file.xom', 'file.xin'],
\ 'opam': ['opam', 'file.opam', 'file.opam.template'],
\ 'openroad': ['file.or'],
@@ -581,6 +582,7 @@ let s:filename_checks = {
\ 'systemverilog': ['file.sv', 'file.svh'],
\ 'tags': ['tags'],
\ 'tak': ['file.tak'],
+ \ 'tal': ['file.tal'],
\ 'taskdata': ['pending.data', 'completed.data', 'undo.data'],
\ 'taskedit': ['file.task'],
\ 'tcl': ['file.tcl', 'file.tm', 'file.tk', 'file.itcl', 'file.itk', 'file.jacl', '.tclshrc', 'tclsh.rc', '.wishrc'],
diff --git a/test/old/testdir/test_syntax.vim b/test/old/testdir/test_syntax.vim
index 45230c4208..886c23efa7 100644
--- a/test/old/testdir/test_syntax.vim
+++ b/test/old/testdir/test_syntax.vim
@@ -116,7 +116,7 @@ func Test_syntime()
let a = execute('syntime clear')
call assert_equal("\nNo Syntax items defined for this buffer", a)
- view samples/memfile_test.c
+ view ../memfile_test.c
setfiletype cpp
redraw
let a = execute('syntime report')