aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml3
-rw-r--r--.github/workflows/coverity-scan.yml2
-rw-r--r--.github/workflows/vim-patches.yml2
-rw-r--r--runtime/doc/treesitter.txt62
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua21
-rw-r--r--runtime/lua/vim/treesitter/query.lua27
-rwxr-xr-xscripts/vim-patch.sh4
-rw-r--r--src/nvim/ex_docmd.c25
-rw-r--r--src/nvim/testdir/test_excmd.vim8
-rw-r--r--src/nvim/window.c1
-rw-r--r--test/functional/core/job_spec.lua1
-rw-r--r--test/functional/legacy/fixeol_spec.lua11
-rw-r--r--test/functional/ui/inccommand_spec.lua102
-rw-r--r--test/functional/ui/winbar_spec.lua19
14 files changed, 231 insertions, 57 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4657053167..16464426ee 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -120,7 +120,8 @@ jobs:
- if: "!cancelled()"
name: uncrustify
run: |
- ${{ env.CACHE_UNCRUSTIFY }} -c ./src/uncrustify.cfg -q --check $(find ./src/nvim -name "*.[ch]") >/dev/null
+ ${{ env.CACHE_UNCRUSTIFY }} -c ./src/uncrustify.cfg -q --replace --no-backup $(find ./src/nvim -name "*.[ch]")
+ git diff --color --exit-code
- if: "!cancelled()"
name: lualint
diff --git a/.github/workflows/coverity-scan.yml b/.github/workflows/coverity-scan.yml
index 064da54456..ce7822b5c1 100644
--- a/.github/workflows/coverity-scan.yml
+++ b/.github/workflows/coverity-scan.yml
@@ -6,7 +6,7 @@ on:
jobs:
scan:
- runs-on: ubuntu-18.04
+ runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
diff --git a/.github/workflows/vim-patches.yml b/.github/workflows/vim-patches.yml
index 45e6b81aed..df8c8116b5 100644
--- a/.github/workflows/vim-patches.yml
+++ b/.github/workflows/vim-patches.yml
@@ -5,7 +5,7 @@ on:
jobs:
update-vim-patches:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 339ae0c2ed..52b415bbd1 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -261,36 +261,37 @@ for a node or match and perform side effects. For example, the |set!|
predicate sets metadata on the match or node : >
((identifier) @foo (#set! "type" "parameter"))
-Here is a list of built-in directives:
+Built-in directives:
- `set!` *ts-directive-set!*
- Sets key/value metadata for a specific node or match : >
- ((identifier) @foo (#set! @foo "kind" "parameter"))
- ((node1) @left (node2) @right (#set! "type" "pair"))
+ `set!` *ts-directive-set!*
+ Sets key/value metadata for a specific match or capture.
+ Value is accessible as either `metadata[key]` (match
+ specific) or `metadata[capture_id][key]` (capture specific).
+
+ Parameters: ~
+ {capture_id} (optional)
+ {key}
+ {value}
+
+ Examples: >
+ ((identifier) @foo (#set! @foo "kind" "parameter"))
+ ((node1) @left (node2) @right (#set! "type" "pair"))
<
- `offset!` *ts-directive-offset!*
- Takes the range of the captured node and applies the offsets
- to it's range : >
- ((identifier) @constant (#offset! @constant 0 1 0 -1))
-< This will generate a range object for the captured node with
- the offsets applied. The arguments are
- `({capture_id}, {start_row}, {start_col}, {end_row}, {end_col}, {key?})`
- The default key is "offset".
-
- *vim.treesitter.query.add_directive()*
-vim.treesitter.query.add_directive({name}, {handler})
-
-This adds a directive with the name {name} to be used in queries.
-{handler} should be a function whose signature will be : >
- handler(match, pattern, bufnr, predicate, metadata)
-Handlers can set match level data by setting directly on the metadata object
-`metadata.key = value` Handlers can set node level data by using the capture
-id on the metadata table `metadata[capture_id].key = value`
+ `offset!` *ts-directive-offset!*
+ Takes the range of the captured node and applies an offset.
+ This will generate a new range object for the captured node
+ as `metadata[capture_id].range`.
- *vim.treesitter.query.list_directives()*
-vim.treesitter.query.list_directives()
+ Parameters: ~
+ {capture_id}
+ {start_row}
+ {start_col}
+ {end_row}
+ {end_col}
-This lists the currently available directives to use in queries.
+ Example: >
+ ((identifier) @constant (#offset! @constant 0 1 0 -1))
+<
Treesitter syntax highlighting (WIP) *lua-treesitter-highlight*
@@ -409,10 +410,15 @@ Lua module: vim.treesitter.query *treesitter-query*
add_directive({name}, {handler}, {force}) *add_directive()*
Adds a new directive to be used in queries
+ Handlers can set match level data by setting directly on the
+ metadata object `metadata.key = value`, additionally, handlers
+ can set node level data by using the capture id on the
+ metadata table `metadata[capture_id].key = value`
+
Parameters: ~
{name} the name of the directive, without leading #
{handler} the handler function to be used signature will
- be (match, pattern, bufnr, predicate)
+ be (match, pattern, bufnr, predicate, metadata)
add_predicate({name}, {handler}, {force}) *add_predicate()*
Adds a new predicate to be used in queries
@@ -451,6 +457,8 @@ get_query_files({lang}, {query_name}, {is_included})
as `nil`
list_directives() *list_directives()*
+ Lists the currently available directives to use in queries.
+
Return: ~
The list of supported directives.
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index 57d8c5fd21..5a05a29da8 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -295,6 +295,14 @@ function LanguageTree:included_regions()
return self._regions
end
+---@private
+local function get_node_range(node, id, metadata)
+ if metadata[id] and metadata[id].range then
+ return metadata[id].range
+ end
+ return { node:range() }
+end
+
--- Gets language injection points by language.
---
--- This is where most of the injection processing occurs.
@@ -327,10 +335,10 @@ function LanguageTree:_get_injections()
-- Allow for captured nodes to be used
if type(content) == 'number' then
- content = { match[content] }
+ content = { match[content]:range() }
end
- if content then
+ if type(content) == 'table' and #content >= 4 then
vim.list_extend(ranges, content)
end
end
@@ -351,7 +359,7 @@ function LanguageTree:_get_injections()
elseif name == 'combined' then
combined = true
elseif name == 'content' and #ranges == 0 then
- table.insert(ranges, node)
+ table.insert(ranges, get_node_range(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
@@ -360,7 +368,7 @@ function LanguageTree:_get_injections()
end
if #ranges == 0 then
- table.insert(ranges, node)
+ table.insert(ranges, get_node_range(node, id, metadata))
end
end
end
@@ -397,7 +405,10 @@ function LanguageTree:_get_injections()
for _, entry in pairs(patterns) do
if entry.combined then
- table.insert(result[lang], vim.tbl_flatten(entry.regions))
+ local regions = vim.tbl_map(function(e)
+ return vim.tbl_flatten(e)
+ end, entry.regions)
+ table.insert(result[lang], regions)
else
for _, ranges in ipairs(entry.regions) do
table.insert(result[lang], ranges)
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 3c4c8fdb96..0cc2b6d2a4 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -313,20 +313,22 @@ local directive_handlers = {
['set!'] = function(_, _, _, pred, metadata)
if #pred == 4 then
-- (#set! @capture "key" "value")
- local capture = pred[2]
- if not metadata[capture] then
- metadata[capture] = {}
+ local _, capture_id, key, value = unpack(pred)
+ if not metadata[capture_id] then
+ metadata[capture_id] = {}
end
- metadata[capture][pred[3]] = pred[4]
+ metadata[capture_id][key] = value
else
+ local _, key, value = unpack(pred)
-- (#set! "key" "value")
- metadata[pred[2]] = pred[3]
+ metadata[key] = value
end
end,
-- Shifts the range of a node.
-- Example: (#offset! @_node 0 1 0 -1)
['offset!'] = function(match, _, _, pred, metadata)
- local offset_node = match[pred[2]]
+ local capture_id = pred[2]
+ local offset_node = match[capture_id]
local range = { offset_node:range() }
local start_row_offset = pred[3] or 0
local start_col_offset = pred[4] or 0
@@ -340,7 +342,10 @@ local directive_handlers = {
-- If this produces an invalid range, we just skip it.
if range[1] < range[3] or (range[1] == range[3] and range[2] <= range[4]) then
- metadata.content = { range }
+ if not metadata[capture_id] then
+ metadata[capture_id] = {}
+ end
+ metadata[capture_id].range = range
end
end,
}
@@ -360,9 +365,14 @@ end
--- Adds a new directive to be used in queries
---
+--- Handlers can set match level data by setting directly on the
+--- metadata object `metadata.key = value`, additionally, handlers
+--- can set node level data by using the capture id on the
+--- metadata table `metadata[capture_id].key = value`
+---
---@param name the name of the directive, without leading #
---@param handler the handler function to be used
---- signature will be (match, pattern, bufnr, predicate)
+--- signature will be (match, pattern, bufnr, predicate, metadata)
function M.add_directive(name, handler, force)
if directive_handlers[name] and not force then
error(string.format('Overriding %s', name))
@@ -371,6 +381,7 @@ function M.add_directive(name, handler, force)
directive_handlers[name] = handler
end
+--- Lists the currently available directives to use in queries.
---@return The list of supported directives.
function M.list_directives()
return vim.tbl_keys(directive_handlers)
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 8235949156..472b79cbf4 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -4,6 +4,8 @@ set -e
set -u
# Use privileged mode, which e.g. skips using CDPATH.
set -p
+# https://www.shellcheck.net/wiki/SC2031
+shopt -s lastpipe
# Ensure that the user has a bash that supports -A
if [[ "${BASH_VERSINFO[0]}" -lt 4 ]]; then
@@ -345,7 +347,7 @@ stage_patch() {
See the wiki for more information:
* https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim
-' "${vim_version}" "${BASENAME}" "${BASENAME}"
+' "${vim_version}" "${BASENAME}" "${BASENAME}" "${BASENAME}"
return $ret
}
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 4b7958efa5..e6ee0046af 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -2751,6 +2751,8 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
{
int address_count = 1;
linenr_T lnum;
+ bool need_check_cursor = false;
+ int ret = FAIL;
// Repeat for all ',' or ';' separated addresses.
for (;;) {
@@ -2760,7 +2762,7 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
lnum = get_address(eap, &eap->cmd, eap->addr_type, eap->skip, silent,
eap->addr_count == 0, address_count++);
if (eap->cmd == NULL) { // error detected
- return FAIL;
+ goto theend;
}
if (lnum == MAXLNUM) {
if (*eap->cmd == '%') { // '%' - all lines
@@ -2799,14 +2801,14 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
// there is no Vim command which uses '%' and
// ADDR_WINDOWS or ADDR_TABS
*errormsg = _(e_invrange);
- return FAIL;
+ goto theend;
}
break;
case ADDR_TABS_RELATIVE:
case ADDR_UNSIGNED:
case ADDR_QUICKFIX:
*errormsg = _(e_invrange);
- return FAIL;
+ goto theend;
case ADDR_ARGUMENTS:
if (ARGCOUNT == 0) {
eap->line1 = eap->line2 = 0;
@@ -2831,19 +2833,19 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
// '*' - visual area
if (eap->addr_type != ADDR_LINES) {
*errormsg = _(e_invrange);
- return FAIL;
+ goto theend;
}
eap->cmd++;
if (!eap->skip) {
pos_T *fp = getmark('<', false);
if (check_mark(fp) == FAIL) {
- return FAIL;
+ goto theend;
}
eap->line1 = fp->lnum;
fp = getmark('>', false);
if (check_mark(fp) == FAIL) {
- return FAIL;
+ goto theend;
}
eap->line2 = fp->lnum;
eap->addr_count++;
@@ -2857,11 +2859,14 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
if (*eap->cmd == ';') {
if (!eap->skip) {
curwin->w_cursor.lnum = eap->line2;
+
// Don't leave the cursor on an illegal line or column, but do
// accept zero as address, so 0;/PATTERN/ works correctly.
+ // Check the cursor position before returning.
if (eap->line2 > 0) {
check_cursor();
}
+ need_check_cursor = true;
}
} else if (*eap->cmd != ',') {
break;
@@ -2877,7 +2882,13 @@ int parse_cmd_address(exarg_T *eap, char **errormsg, bool silent)
eap->addr_count = 0;
}
}
- return OK;
+ ret = OK;
+
+theend:
+ if (need_check_cursor) {
+ check_cursor();
+ }
+ return ret;
}
/// Check for an Ex command with optional tail.
diff --git a/src/nvim/testdir/test_excmd.vim b/src/nvim/testdir/test_excmd.vim
index 8055a51a11..7dde8a0439 100644
--- a/src/nvim/testdir/test_excmd.vim
+++ b/src/nvim/testdir/test_excmd.vim
@@ -422,5 +422,13 @@ func Test_address_line_overflow()
bwipe!
endfunc
+" This was leaving the cursor in line zero
+func Test_using_zero_in_range()
+ new
+ norm o00
+ silent! 0;s/\%')
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 060f498f07..a41f3362d2 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -3993,6 +3993,7 @@ void win_init_size(void)
firstwin->w_height = ROWS_AVAIL;
firstwin->w_height_inner = firstwin->w_height - firstwin->w_winbar_height;
firstwin->w_height_outer = firstwin->w_height;
+ firstwin->w_winrow_off = firstwin->w_winbar_height;
topframe->fr_height = ROWS_AVAIL;
firstwin->w_width = Columns;
firstwin->w_width_inner = firstwin->w_width;
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index cf24e570cb..461a69f357 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -682,6 +682,7 @@ describe('jobs', function()
-- User can explicitly set $NVIM_LOG_FILE, $VIM, $VIMRUNTIME.
eq('NVIM_LOG_FILE=Xtest_jobstart_env',
get_env_in_child_job('NVIM_LOG_FILE', { NVIM_LOG_FILE='Xtest_jobstart_env' }))
+ os.remove('Xtest_jobstart_env')
end)
describe('jobwait', function()
diff --git a/test/functional/legacy/fixeol_spec.lua b/test/functional/legacy/fixeol_spec.lua
index d3ff86d349..3cc9d54e2b 100644
--- a/test/functional/legacy/fixeol_spec.lua
+++ b/test/functional/legacy/fixeol_spec.lua
@@ -6,12 +6,11 @@ local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers
describe('fixeol', function()
local function rmtestfiles()
- feed_command('%bwipeout!')
- feed_command('call delete("test.out")')
- feed_command('call delete("XXEol")')
- feed_command('call delete("XXNoEol")')
- feed_command('call delete("XXTestEol")')
- feed_command('call delete("XXTestNoEol")')
+ os.remove("test.out")
+ os.remove("XXEol")
+ os.remove("XXNoEol")
+ os.remove("XXTestEol")
+ os.remove("XXTestNoEol")
end
setup(function()
clear()
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua
index fb80444430..a1ff778da1 100644
--- a/test/functional/ui/inccommand_spec.lua
+++ b/test/functional/ui/inccommand_spec.lua
@@ -1343,6 +1343,108 @@ describe(":substitute, inccommand=split", function()
]])
end)
+ it([[preview changes correctly with c_CTRL-R_= and c_CTRL-\_e]], function()
+ feed('gg')
+ feed(":1,2s/t/X")
+ screen:expect([[
+ Inc subs{12:X}itution on |
+ {12:X}wo lines |
+ Inc substitution on |
+ two lines |
+ |
+ {11:[No Name] [+] }|
+ |1| Inc subs{12:X}itution on |
+ |2| {12:X}wo lines |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :1,2s/t/X^ |
+ ]])
+
+ feed([[<C-R>='Y']])
+ -- preview should be unchanged during c_CTRL-R_= editing
+ screen:expect([[
+ Inc subs{12:X}itution on |
+ {12:X}wo lines |
+ Inc substitution on |
+ two lines |
+ |
+ {11:[No Name] [+] }|
+ |1| Inc subs{12:X}itution on |
+ |2| {12:X}wo lines |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ ={1:'Y'}^ |
+ ]])
+
+ feed('<CR>')
+ -- preview should be changed by the result of the expression
+ screen:expect([[
+ Inc subs{12:XY}itution on |
+ {12:XY}wo lines |
+ Inc substitution on |
+ two lines |
+ |
+ {11:[No Name] [+] }|
+ |1| Inc subs{12:XY}itution on |
+ |2| {12:XY}wo lines |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ :1,2s/t/XY^ |
+ ]])
+
+ feed([[<C-\>e'echo']])
+ -- preview should be unchanged during c_CTRL-\_e editing
+ screen:expect([[
+ Inc subs{12:XY}itution on |
+ {12:XY}wo lines |
+ Inc substitution on |
+ two lines |
+ |
+ {11:[No Name] [+] }|
+ |1| Inc subs{12:XY}itution on |
+ |2| {12:XY}wo lines |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {10:[Preview] }|
+ ={1:'echo'}^ |
+ ]])
+
+ feed('<CR>')
+ -- preview should be cleared if command is changed to a non-previewable one
+ screen:expect([[
+ Inc substitution on |
+ two lines |
+ Inc substitution on |
+ two lines |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :echo^ |
+ ]])
+ end)
+
end)
describe("inccommand=nosplit", function()
diff --git a/test/functional/ui/winbar_spec.lua b/test/functional/ui/winbar_spec.lua
index 982d2d67fd..92a6ab2e84 100644
--- a/test/functional/ui/winbar_spec.lua
+++ b/test/functional/ui/winbar_spec.lua
@@ -26,6 +26,8 @@ describe('winbar', function()
[7] = {background = Screen.colors.LightGrey},
[8] = {background = Screen.colors.LightMagenta},
[9] = {bold = true, foreground = Screen.colors.Blue, background = Screen.colors.LightMagenta},
+ [10] = {background = Screen.colors.LightGrey, underline = true},
+ [11] = {background = Screen.colors.LightGrey, underline = true, bold = true, foreground = Screen.colors.Magenta},
})
meths.set_option('winbar', 'Set Up The Bars')
end)
@@ -245,6 +247,23 @@ describe('winbar', function()
{4:[No Name] }|
|
]])
+ -- Test for issue #18791
+ command('tabnew')
+ screen:expect([[
+ {10: }{11:4}{10: [No Name] }{1: [No Name] }{2: }{10:X}|
+ {1:Set Up The Bars }|
+ ^ |
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {4:[No Name] }|
+ |
+ ]])
end)
it('mouse click and drag work correctly in buffer', function()