aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/api-docs.yml4
-rwxr-xr-xci/snap/deploy.sh4
-rw-r--r--runtime/autoload/health.vim2
-rw-r--r--runtime/autoload/health/provider.vim2
-rw-r--r--runtime/doc/api.txt253
-rw-r--r--runtime/doc/lua.txt16
-rw-r--r--runtime/doc/message.txt2
-rw-r--r--runtime/ftplugin/cpp.vim1
-rw-r--r--runtime/lua/vim/filetype.lua2
-rw-r--r--runtime/lua/vim/shared.lua27
-rw-r--r--src/nvim/api/autocmd.c199
-rw-r--r--src/nvim/buffer.c24
-rw-r--r--src/nvim/fileio.c2
-rw-r--r--src/nvim/ops.c2
-rw-r--r--src/nvim/screen.c2
-rw-r--r--src/nvim/testdir/test_autocmd.vim13
-rw-r--r--src/nvim/testdir/test_display.vim21
-rw-r--r--src/nvim/testdir/test_quickfix.vim202
-rw-r--r--src/nvim/tui/tui.c28
-rw-r--r--src/nvim/ui_client.c8
-rw-r--r--test/functional/legacy/display_spec.lua36
-rw-r--r--test/functional/lua/vim_spec.lua6
-rw-r--r--test/functional/plugin/matchparen_spec.lua2
-rw-r--r--test/functional/ui/fold_spec.lua2
-rw-r--r--third-party/CMakeLists.txt4
25 files changed, 588 insertions, 276 deletions
diff --git a/.github/workflows/api-docs.yml b/.github/workflows/api-docs.yml
index 561524f64a..2e22a1200f 100644
--- a/.github/workflows/api-docs.yml
+++ b/.github/workflows/api-docs.yml
@@ -1,5 +1,5 @@
# Autogenerate the API docs on new commit to important branches
-# Also work as a check for PR's to not forget commiting their doc changes
+# Also work as a check for PR's to not forget committing their doc changes
# called from api-docs-check.yml
name: Autogenerate API docs
on:
@@ -52,7 +52,7 @@ jobs:
python3 scripts/gen_vimdoc.py
printf '::set-output name=UPDATED_DOCS::%s\n' $([ -z "$(git diff)" ]; echo $?)
- - name: FAIL, PR has not commited doc changes
+ - name: FAIL, PR has not committed doc changes
if: ${{ steps.docs.outputs.UPDATED_DOCS != 0 && inputs.check_only }}
run: |
echo "Job failed, run ./scripts/gen_vimdoc.py and commit your doc changes"
diff --git a/ci/snap/deploy.sh b/ci/snap/deploy.sh
index 8429059e22..1794fc61d9 100755
--- a/ci/snap/deploy.sh
+++ b/ci/snap/deploy.sh
@@ -8,7 +8,7 @@ WEBHOOK_PAYLOAD="$(cat "${SNAP_DIR}/.snapcraft_payload")"
PAYLOAD_SIG="${SECRET_SNAP_SIG}"
-snap_realease_needed() {
+snap_release_needed() {
last_committed_tag="$(git tag -l --sort=refname|head -1)"
last_snap_release="$(snap info nvim | awk '$1 == "latest/edge:" { print $2 }' | perl -lpe 's/v\d.\d.\d-//g')"
git fetch -f --tags
@@ -33,7 +33,7 @@ trigger_snapcraft_webhook() {
}
-if $(snap_realease_needed); then
+if $(snap_release_needed); then
echo "New snap release required"
trigger_snapcraft_webhook
fi
diff --git a/runtime/autoload/health.vim b/runtime/autoload/health.vim
index ec030adf04..1292e4344e 100644
--- a/runtime/autoload/health.vim
+++ b/runtime/autoload/health.vim
@@ -188,7 +188,7 @@ function! s:get_healthcheck_list(plugin_names) abort
\ + nvim_get_runtime_file('lua/**/'.p.'/health/init.lua', v:true)
\ + nvim_get_runtime_file('lua/**/'.p.'/health.lua', v:true)
if len(paths) == 0
- let healthchecks += [[p, '', '']] " healthchek not found
+ let healthchecks += [[p, '', '']] " healthcheck not found
else
let healthchecks += map(uniq(sort(paths)),
\'<SID>filepath_to_healthcheck(v:val)')
diff --git a/runtime/autoload/health/provider.vim b/runtime/autoload/health/provider.vim
index 6022e05c22..a01cb9631c 100644
--- a/runtime/autoload/health/provider.vim
+++ b/runtime/autoload/health/provider.vim
@@ -690,7 +690,7 @@ function! s:check_perl() abort
if empty(perl_exec)
if !empty(perl_warnings)
call health#report_warn(perl_warnings, ['See :help provider-perl for more information.',
- \ 'You may disable this provider (and warning) by adding `let g:loaded_node_provider = 0` to your init.vim'])
+ \ 'You may disable this provider (and warning) by adding `let g:loaded_perl_provider = 0` to your init.vim'])
else
call health#report_warn('No usable perl executable found')
endif
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index fa2f8f974a..02a27e15f8 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -452,7 +452,7 @@ Extended marks (extmarks) represent buffer annotations that track text changes
in the buffer. They can represent cursors, folds, misspelled words, anything
that needs to track a logical location in the buffer over time. |api-indexing|
-Extmark position works like "bar" cursor: it exists between characters. Thus
+Extmark position works like "bar" cursor: it exists between characters. Thus,
the maximum extmark index on a line is 1 more than the character index: >
f o o b a r line contents
@@ -468,7 +468,7 @@ extmark position and enter some text, the extmark migrates forward. >
f o o z|b a r line (| = cursor)
4 extmark (after typing "z")
-If an extmark is on the last index of a line and you inputs a newline at that
+If an extmark is on the last index of a line and you input a newline at that
point, the extmark will accordingly migrate to the next line: >
f o o z b a r| line (| = cursor)
@@ -3152,129 +3152,204 @@ nvim_tabpage_set_var({tabpage}, {name}, {value})
Autocmd Functions *api-autocmd*
nvim_create_augroup({name}, {*opts}) *nvim_create_augroup()*
- Create or get an augroup.
+ Create or get an autocommand group |autocmd-groups|.
- To get an existing augroup ID, do: >
- local id = vim.api.nvim_create_augroup(name, {
+ To get an existing group id, do: >
+ local id = vim.api.nvim_create_augroup("MyGroup", {
clear = false
})
<
Parameters: ~
- {name} String: The name of the augroup to create
- {opts} Parameters
- • clear (bool): Whether to clear existing commands
- or not. Defaults to true. See |autocmd-groups|
+ {name} String: The name of the group
+ {opts} Dictionary Parameters
+ • clear (bool) optional: defaults to true. Clear
+ existing commands if the group already exists
+ |autocmd-groups|.
Return: ~
- opaque value to use with nvim_del_augroup_by_id
+ Integer id of the created group.
+
+ See also: ~
+ |autocmd-groups|
nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()*
- Create an autocmd.
+ Create an |autocommand|
- Examples:
- • event: "pat1,pat2,pat3",
- • event: "pat1"
- • event: { "pat1" }
- • event: { "pat1", "pat2", "pat3" }
+ The API allows for two (mutually exclusive) types of actions
+ to be executed when the autocommand triggers: a callback
+ function (Lua or Vimscript), or a command (like regular
+ autocommands).
- Parameters: ~
- {event} The event or events to register this autocmd
- Required keys: event: string | ArrayOf(string)
+ Example using callback: >
+ -- Lua function
+ local myluafun = function() print("This buffer enters") end
- Parameters: ~
- {opts} Optional Parameters:
- • callback: (string|function)
- • (string): The name of the viml function to
- execute when triggering this autocmd
- • (function): The lua function to execute when
- triggering this autocmd
- • NOTE: Cannot be used with {command}
+ -- Vimscript function name (as a string)
+ local myvimfun = "g:MyVimFunction"
- • command: (string) command
- • vimscript command
- • NOTE: Cannot be used with {callback} Eg.
- command = "let g:value_set = v:true"
+ vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, {
+ pattern = {"*.c", "*.h"},
+ callback = myluafun, -- Or myvimfun
+ })
+<
+
+ Example using command: >
+ vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, {
+ pattern = {"*.c", "*.h"},
+ command = "echo 'Entering a C or C++ file'",
+ })
+<
- • pattern: (string|table)
- • pattern or patterns to match against
- • defaults to "*".
- • NOTE: Cannot be used with {buffer}
+ Example values for pattern: >
+ pattern = "*.py"
+ pattern = { "*.py", "*.pyi" }
+<
- • buffer: (bufnr)
- • create a |autocmd-buflocal| autocmd.
- • NOTE: Cannot be used with {pattern}
+ Examples values for event: >
+ "BufPreWrite"
+ {"CursorHold", "BufPreWrite", "BufPostWrite"}
+<
- • group: (string|int) The augroup name or id
- • once: (boolean) - See |autocmd-once|
- • nested: (boolean) - See |autocmd-nested|
- • desc: (string) - Description of the autocmd
+ Parameters: ~
+ {event} (String|Array) The event or events to register
+ this autocommand
+ {opts} Dictionary of autocommand options:
+ • group (string|integer) optional: the
+ autocommand group name or id to match against.
+ • pattern (string|array) optional: pattern or
+ patterns to match against |autocmd-pattern|.
+ • buffer (integer) optional: buffer number for
+ buffer local autocommands |autocmd-buflocal|.
+ Cannot be used with {pattern}.
+ • desc (string) optional: description of the
+ autocommand.
+ • callback (function|string) optional: Lua
+ function or Vim function (as string) to execute
+ on event. Cannot be used with {command}
+ • command (string) optional: Vim command to
+ execute on event. Cannot be used with
+ {callback}
+ • once (boolean) optional: defaults to false. Run
+ the autocommand only once |autocmd-once|.
+ • nested (boolean) optional: defaults to false.
+ Run nested autocommands |autocmd-nested|.
+
+ Return: ~
+ Integer id of the created autocommand.
- Return: ~
- opaque value to use with nvim_del_autocmd
+ See also: ~
+ |autocommand|
+ |nvim_del_autocmd()|
nvim_del_augroup_by_id({id}) *nvim_del_augroup_by_id()*
- Delete an augroup by {id}. {id} can only be returned when
- augroup was created with |nvim_create_augroup|.
+ Delete an autocommand group by id.
- NOTE: behavior differs from augroup-delete.
+ To get a group id one can use |nvim_get_autocmds()|.
- When deleting an augroup, autocmds contained by this augroup
- will also be deleted and cleared. This augroup will no longer
- exist
+ NOTE: behavior differs from |augroup-delete|. When deleting a
+ group, autocommands contained in this group will also be
+ deleted and cleared. This group will no longer exist.
-nvim_del_augroup_by_name({name}) *nvim_del_augroup_by_name()*
- Delete an augroup by {name}.
+ Parameters: ~
+ {id} Integer The id of the group.
- NOTE: behavior differs from augroup-delete.
+ See also: ~
+ |nvim_del_augroup_by_name()|
+ |nvim_create_augroup()|
- When deleting an augroup, autocmds contained by this augroup
- will also be deleted and cleared. This augroup will no longer
- exist
+nvim_del_augroup_by_name({name}) *nvim_del_augroup_by_name()*
+ Delete an autocommand group by name.
-nvim_del_autocmd({id}) *nvim_del_autocmd()*
- Delete an autocmd by {id}. Autocmds only return IDs when
- created via the API. Will not error if called and no autocmds
- match the {id}.
+ NOTE: behavior differs from |augroup-delete|. When deleting a
+ group, autocommands contained in this group will also be
+ deleted and cleared. This group will no longer exist.
Parameters: ~
- {id} Integer The ID returned by nvim_create_autocmd
+ {name} String The name of the group.
-nvim_do_autocmd({event}, {*opts}) *nvim_do_autocmd()*
- Do one autocmd.
+ See also: ~
+ |autocommand-groups|
+
+nvim_del_autocmd({id}) *nvim_del_autocmd()*
+ Delete an autocommand by id.
+
+ NOTE: Only autocommands created via the API have an id.
Parameters: ~
- {event} The event or events to execute
- {opts} Optional Parameters:
- • buffer (number) - buffer number
- • NOTE: Cannot be used with {pattern}
+ {id} Integer The id returned by nvim_create_autocmd
- • pattern (string|table) - optional, defaults to
- "*".
- • NOTE: Cannot be used with {buffer}
+ See also: ~
+ |nvim_create_autocmd()|
- • group (string|int) - autocmd group name or id
- • modeline (boolean) - Default true, see
- |<nomodeline>|
+nvim_do_autocmd({event}, {*opts}) *nvim_do_autocmd()*
+ Execute an autocommand |autocmd-execute|.
+
+ Parameters: ~
+ {event} (String|Array) The event or events to execute
+ {opts} Dictionary of autocommand options:
+ • group (string|integer) optional: the
+ autocommand group name or id to match against.
+ |autocmd-groups|.
+ • pattern (string|array) optional: defaults to
+ "*" |autocmd-pattern|. Cannot be used with
+ {buffer}.
+ • buffer (integer) optional: buffer number
+ |autocmd-buflocal|. Cannot be used with
+ {pattern}.
+ • modeline (bool) optional: defaults to true.
+ Process the modeline after the autocommands
+ |<nomodeline>|.
-nvim_get_autocmds({*opts}) *nvim_get_autocmds()*
- Get autocmds that match the requirements passed to {opts}.
+ See also: ~
+ |:doautocmd|
- Parameters: ~
- {opts} Optional Parameters:
- • event : Name or list of name of events to match
- against
- • group (string|int): Name or id of group to match
- against
- • pattern: Pattern or list of patterns to match
- against. Cannot be used with {buffer}
- • buffer: Buffer number or list of buffer numbers
- for buffer local autocommands
- |autocmd-buflocal|. Cannot be used with
- {pattern}
+nvim_get_autocmds({*opts}) *nvim_get_autocmds()*
+ Get autocommands that match the requirements passed to {opts}.
+
+ These examples will get autocommands matching ALL the given
+ criteria: >
+ -- Matches all criteria
+ autocommands = vim.api.nvim_get_autocmds({
+ group = "MyGroup",
+ event = {"BufEnter", "BufWinEnter"},
+ pattern = {"*.c", "*.h"}
+ })
+
+ -- All commands from one group
+ autocommands = vim.api.nvim_get_autocmds({
+ group = "MyGroup",
+ })
+<
- Return: ~
- A list of autocmds that match
+ NOTE: When multiple patterns or events are provided, it will
+ find all the autocommands that match any combination of them.
+
+ Parameters: ~
+ {opts} Dictionary with at least one of the following:
+ • group (string|integer): the autocommand group
+ name or id to match against.
+ • event (string|array): event or events to match
+ against |autocmd-events|.
+ • pattern (string|array): pattern or patterns to
+ match against |autocmd-pattern|.
+
+ Return: ~
+ Array of autocommands matching the criteria, with each
+ item containing the following fields:
+ • id (number): the autocommand id (only when defined with
+ the API).
+ • group (integer): the autocommand group id.
+ • desc (string): the autocommand description.
+ • event (string): the autocommand event.
+ • command (string): the autocommand command.
+ • once (boolean): whether the autocommand is only run
+ once.
+ • pattern (string): the autocommand pattern. If the
+ autocommand is buffer local |autocmd-buffer-local|:
+ • buflocal (boolean): true if the autocommand is buffer
+ local.
+ • buffer (number): the buffer number.
==============================================================================
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index bd821c4f9e..21f44ce02e 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -1634,6 +1634,22 @@ tbl_flatten({t}) *vim.tbl_flatten()*
See also: ~
From https://github.com/premake/premake-core/blob/master/src/base/table.lua
+tbl_get({o}, {...}) *vim.tbl_get()*
+ Index into a table (first argument) via string keys passed as
+ subsequent arguments. Return `nil` if the key does not exist. Examples: >
+
+ vim.tbl_get({ key = { nested_key = true }}, 'key', 'nested_key') == true
+ vim.tbl_get({ key = {}}, 'key', 'nested_key') == nil
+<
+
+ Parameters: ~
+ {o} Table to index
+ {...} Optional strings (0 or more, variadic) via which to
+ index the table
+
+ Return: ~
+ nested value indexed by key if it exists, else nil
+
tbl_isempty({t}) *vim.tbl_isempty()*
Checks if a table is empty.
diff --git a/runtime/doc/message.txt b/runtime/doc/message.txt
index fa1bc6f7da..dac4df5ee9 100644
--- a/runtime/doc/message.txt
+++ b/runtime/doc/message.txt
@@ -61,7 +61,7 @@ If you are lazy, it also works without the shift key: >
When an error message is displayed, but it is removed before you could read
it, you can see it again with: >
- :echo errmsg
+ :echo v:errmsg
Or view a list of recent messages with: >
:messages
See `:messages` above.
diff --git a/runtime/ftplugin/cpp.vim b/runtime/ftplugin/cpp.vim
index f9d31cbec3..58c4e4b24a 100644
--- a/runtime/ftplugin/cpp.vim
+++ b/runtime/ftplugin/cpp.vim
@@ -10,6 +10,7 @@ endif
" Behaves mostly just like C
runtime! ftplugin/c.vim ftplugin/c_*.vim ftplugin/c/*.vim
+runtime! ftplugin/c.lua ftplugin/c_*.lua ftplugin/c/*.lua
" C++ uses templates with <things>
" Disabled, because it gives an error for typing an unmatched ">".
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index b356f5e3dc..ab71de54f8 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -21,7 +21,7 @@ end
---@private
local function getline(bufnr, lnum)
- return api.nvim_buf_get_lines(bufnr, lnum-1, lnum, false)[1]
+ return api.nvim_buf_get_lines(bufnr, lnum-1, lnum, false)[1] or ""
end
-- Filetypes based on file extension
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 3eb332279a..f0dc34608c 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -347,6 +347,33 @@ function vim.tbl_add_reverse_lookup(o)
return o
end
+--- Index into a table (first argument) via string keys passed as subsequent arguments.
+--- Return `nil` if the key does not exist.
+--_
+--- Examples:
+--- <pre>
+--- vim.tbl_get({ key = { nested_key = true }}, 'key', 'nested_key') == true
+--- vim.tbl_get({ key = {}}, 'key', 'nested_key') == nil
+--- </pre>
+---
+---@param o Table to index
+---@param ... Optional strings (0 or more, variadic) via which to index the table
+---
+---@returns nested value indexed by key if it exists, else nil
+function vim.tbl_get(o, ...)
+ local keys = {...}
+ if #keys == 0 then
+ return
+ end
+ for _, k in ipairs(keys) do
+ o = o[k]
+ if o == nil then
+ return
+ end
+ end
+ return o
+end
+
--- Extends a list-like table with the values of another list-like table.
---
--- NOTE: This mutates dst!
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index 8a7dd00b2a..9aaa0418dc 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -36,16 +36,42 @@
// Used to delete autocmds from nvim_del_autocmd
static int64_t next_autocmd_id = 1;
-/// Get autocmds that match the requirements passed to {opts}.
+/// Get autocommands that match the requirements passed to {opts}.
///
-/// @param opts Optional Parameters:
-/// - event : Name or list of name of events to match against
-/// - group (string|int): Name or id of group to match against
-/// - pattern: Pattern or list of patterns to match against. Cannot be used with {buffer}
-/// - buffer: Buffer number or list of buffer numbers for buffer local autocommands
-/// |autocmd-buflocal|. Cannot be used with {pattern}
+/// These examples will get autocommands matching ALL the given criteria:
+/// <pre>
+/// -- Matches all criteria
+/// autocommands = vim.api.nvim_get_autocmds({
+/// group = "MyGroup",
+/// event = {"BufEnter", "BufWinEnter"},
+/// pattern = {"*.c", "*.h"}
+/// })
+///
+/// -- All commands from one group
+/// autocommands = vim.api.nvim_get_autocmds({
+/// group = "MyGroup",
+/// })
+/// </pre>
///
-/// @return A list of autocmds that match
+/// NOTE: When multiple patterns or events are provided, it will find all the autocommands that
+/// match any combination of them.
+///
+/// @param opts Dictionary with at least one of the following:
+/// - group (string|integer): the autocommand group name or id to match against.
+/// - event (string|array): event or events to match against |autocmd-events|.
+/// - pattern (string|array): pattern or patterns to match against |autocmd-pattern|.
+/// @return Array of autocommands matching the criteria, with each item
+/// containing the following fields:
+/// - id (number): the autocommand id (only when defined with the API).
+/// - group (integer): the autocommand group id.
+/// - desc (string): the autocommand description.
+/// - event (string): the autocommand event.
+/// - command (string): the autocommand command.
+/// - once (boolean): whether the autocommand is only run once.
+/// - pattern (string): the autocommand pattern.
+/// If the autocommand is buffer local |autocmd-buffer-local|:
+/// - buflocal (boolean): true if the autocommand is buffer local.
+/// - buffer (number): the buffer number.
Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
FUNC_API_SINCE(9)
{
@@ -301,40 +327,66 @@ cleanup:
return autocmd_list;
}
-/// Create an autocmd.
+/// Create an |autocommand|
+///
+/// The API allows for two (mutually exclusive) types of actions to be executed when the autocommand
+/// triggers: a callback function (Lua or Vimscript), or a command (like regular autocommands).
+///
+/// Example using callback:
+/// <pre>
+/// -- Lua function
+/// local myluafun = function() print("This buffer enters") end
+///
+/// -- Vimscript function name (as a string)
+/// local myvimfun = "g:MyVimFunction"
+///
+/// vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, {
+/// pattern = {"*.c", "*.h"},
+/// callback = myluafun, -- Or myvimfun
+/// })
+/// </pre>
///
-/// @param event The event or events to register this autocmd
-/// Required keys:
-/// event: string | ArrayOf(string)
+/// Example using command:
+/// <pre>
+/// vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, {
+/// pattern = {"*.c", "*.h"},
+/// command = "echo 'Entering a C or C++ file'",
+/// })
+/// </pre>
///
-/// Examples:
-/// - event: "pat1,pat2,pat3",
-/// - event: "pat1"
-/// - event: { "pat1" }
-/// - event: { "pat1", "pat2", "pat3" }
+/// Example values for pattern:
+/// <pre>
+/// pattern = "*.py"
+/// pattern = { "*.py", "*.pyi" }
+/// </pre>
///
-/// @param opts Optional Parameters:
-/// - callback: (string|function)
-/// - (string): The name of the viml function to execute when triggering this autocmd
-/// - (function): The lua function to execute when triggering this autocmd
-/// - NOTE: Cannot be used with {command}
-/// - command: (string) command
-/// - vimscript command
-/// - NOTE: Cannot be used with {callback}
-/// Eg. command = "let g:value_set = v:true"
-/// - pattern: (string|table)
-/// - pattern or patterns to match against
-/// - defaults to "*".
-/// - NOTE: Cannot be used with {buffer}
-/// - buffer: (bufnr)
-/// - create a |autocmd-buflocal| autocmd.
-/// - NOTE: Cannot be used with {pattern}
-/// - group: (string|int) The augroup name or id
-/// - once: (boolean) - See |autocmd-once|
-/// - nested: (boolean) - See |autocmd-nested|
-/// - desc: (string) - Description of the autocmd
+/// Examples values for event:
+/// <pre>
+/// "BufPreWrite"
+/// {"CursorHold", "BufPreWrite", "BufPostWrite"}
+/// </pre>
+///
+/// @param event (String|Array) The event or events to register this autocommand
+/// @param opts Dictionary of autocommand options:
+/// - group (string|integer) optional: the autocommand group name or
+/// id to match against.
+/// - pattern (string|array) optional: pattern or patterns to match
+/// against |autocmd-pattern|.
+/// - buffer (integer) optional: buffer number for buffer local autocommands
+/// |autocmd-buflocal|. Cannot be used with {pattern}.
+/// - desc (string) optional: description of the autocommand.
+/// - callback (function|string) optional: Lua function or Vim function (as string) to
+/// execute on event. Cannot be used with {command}
+/// - command (string) optional: Vim command to execute on event. Cannot be used with
+/// {callback}
+/// - once (boolean) optional: defaults to false. Run the autocommand
+/// only once |autocmd-once|.
+/// - nested (boolean) optional: defaults to false. Run nested
+/// autocommands |autocmd-nested|.
///
-/// @returns opaque value to use with nvim_del_autocmd
+/// @return Integer id of the created autocommand.
+/// @see |autocommand|
+/// @see |nvim_del_autocmd()|
Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autocmd) *opts,
Error *err)
FUNC_API_SINCE(9)
@@ -552,33 +604,32 @@ cleanup:
return autocmd_id;
}
-/// Delete an autocmd by {id}. Autocmds only return IDs when created
-/// via the API. Will not error if called and no autocmds match
-/// the {id}.
+/// Delete an autocommand by id.
///
-/// @param id Integer The ID returned by nvim_create_autocmd
+/// NOTE: Only autocommands created via the API have an id.
+/// @param id Integer The id returned by nvim_create_autocmd
+/// @see |nvim_create_autocmd()|
void nvim_del_autocmd(Integer id)
FUNC_API_SINCE(9)
{
autocmd_delete_id(id);
}
-/// Create or get an augroup.
+/// Create or get an autocommand group |autocmd-groups|.
///
-/// To get an existing augroup ID, do:
+/// To get an existing group id, do:
/// <pre>
-/// local id = vim.api.nvim_create_augroup(name, {
+/// local id = vim.api.nvim_create_augroup("MyGroup", {
/// clear = false
/// })
/// </pre>
///
-/// @param name String: The name of the augroup to create
-/// @param opts Parameters
-/// - clear (bool): Whether to clear existing commands or not.
-/// Defaults to true.
-/// See |autocmd-groups|
-///
-/// @returns opaque value to use with nvim_del_augroup_by_id
+/// @param name String: The name of the group
+/// @param opts Dictionary Parameters
+/// - clear (bool) optional: defaults to true. Clear existing
+/// commands if the group already exists |autocmd-groups|.
+/// @return Integer id of the created group.
+/// @see |autocmd-groups|
Integer nvim_create_augroup(uint64_t channel_id, String name, Dict(create_augroup) *opts,
Error *err)
FUNC_API_SINCE(9)
@@ -604,13 +655,15 @@ Integer nvim_create_augroup(uint64_t channel_id, String name, Dict(create_augrou
return augroup;
}
-/// Delete an augroup by {id}. {id} can only be returned when augroup was
-/// created with |nvim_create_augroup|.
+/// Delete an autocommand group by id.
///
-/// NOTE: behavior differs from augroup-delete.
+/// To get a group id one can use |nvim_get_autocmds()|.
///
-/// When deleting an augroup, autocmds contained by this augroup will also be deleted and cleared.
-/// This augroup will no longer exist
+/// NOTE: behavior differs from |augroup-delete|. When deleting a group, autocommands contained in
+/// this group will also be deleted and cleared. This group will no longer exist.
+/// @param id Integer The id of the group.
+/// @see |nvim_del_augroup_by_name()|
+/// @see |nvim_create_augroup()|
void nvim_del_augroup_by_id(Integer id)
FUNC_API_SINCE(9)
{
@@ -618,28 +671,30 @@ void nvim_del_augroup_by_id(Integer id)
augroup_del(name, false);
}
-/// Delete an augroup by {name}.
+/// Delete an autocommand group by name.
///
-/// NOTE: behavior differs from augroup-delete.
-///
-/// When deleting an augroup, autocmds contained by this augroup will also be deleted and cleared.
-/// This augroup will no longer exist
+/// NOTE: behavior differs from |augroup-delete|. When deleting a group, autocommands contained in
+/// this group will also be deleted and cleared. This group will no longer exist.
+/// @param name String The name of the group.
+/// @see |autocommand-groups|
void nvim_del_augroup_by_name(String name)
FUNC_API_SINCE(9)
{
augroup_del(name.data, false);
}
-/// Do one autocmd.
-///
-/// @param event The event or events to execute
-/// @param opts Optional Parameters:
-/// - buffer (number) - buffer number
-/// - NOTE: Cannot be used with {pattern}
-/// - pattern (string|table) - optional, defaults to "*".
-/// - NOTE: Cannot be used with {buffer}
-/// - group (string|int) - autocmd group name or id
-/// - modeline (boolean) - Default true, see |<nomodeline>|
+/// Execute an autocommand |autocmd-execute|.
+/// @param event (String|Array) The event or events to execute
+/// @param opts Dictionary of autocommand options:
+/// - group (string|integer) optional: the autocommand group name or
+/// id to match against. |autocmd-groups|.
+/// - pattern (string|array) optional: defaults to "*" |autocmd-pattern|. Cannot be used
+/// with {buffer}.
+/// - buffer (integer) optional: buffer number |autocmd-buflocal|. Cannot be used with
+/// {pattern}.
+/// - modeline (bool) optional: defaults to true. Process the
+/// modeline after the autocommands |<nomodeline>|.
+/// @see |:doautocmd|
void nvim_do_autocmd(Object event, Dict(do_autocmd) *opts, Error *err)
FUNC_API_SINCE(9)
{
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index f200f16a5f..4ca752e747 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -1284,8 +1284,10 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
while (jumpidx != curwin->w_jumplistidx) {
buf = buflist_findnr(curwin->w_jumplist[jumpidx].fmark.fnum);
if (buf != NULL) {
- if (buf == curbuf || !buf->b_p_bl) {
- buf = NULL; // skip current and unlisted bufs
+ // Skip current and unlisted bufs. Also skip a quickfix
+ // buffer, it might be deleted soon.
+ if (buf == curbuf || !buf->b_p_bl || bt_quickfix(buf)) {
+ buf = NULL;
} else if (buf->b_ml.ml_mfp == NULL) {
// skip unloaded buf, but may keep it for later
if (bp == NULL) {
@@ -1323,7 +1325,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
continue;
}
// in non-help buffer, try to skip help buffers, and vv
- if (buf->b_help == curbuf->b_help && buf->b_p_bl) {
+ if (buf->b_help == curbuf->b_help && buf->b_p_bl && !bt_quickfix(buf)) {
if (buf->b_ml.ml_mfp != NULL) { // found loaded buffer
break;
}
@@ -1343,7 +1345,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
}
if (buf == NULL) { // No loaded buffer, find listed one
FOR_ALL_BUFFERS(buf2) {
- if (buf2->b_p_bl && buf2 != curbuf) {
+ if (buf2->b_p_bl && buf2 != curbuf && !bt_quickfix(buf2)) {
buf = buf2;
break;
}
@@ -1355,6 +1357,9 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
} else {
buf = curbuf->b_prev;
}
+ if (bt_quickfix(buf)) {
+ buf = NULL;
+ }
}
}
@@ -1486,8 +1491,15 @@ void set_curbuf(buf_T *buf, int action)
// An autocommand may have deleted "buf", already entered it (e.g., when
// it did ":bunload") or aborted the script processing!
// If curwin->w_buffer is null, enter_buffer() will make it valid again
- if ((buf_valid(buf) && buf != curbuf && !aborting()) || curwin->w_buffer == NULL) {
- enter_buffer(buf);
+ bool valid = buf_valid(buf);
+ if ((valid && buf != curbuf && !aborting()) || curwin->w_buffer == NULL) {
+ // If the buffer is not valid but curwin->w_buffer is NULL we must
+ // enter some buffer. Using the last one is hopefully OK.
+ if (!valid) {
+ enter_buffer(lastbuf);
+ } else {
+ enter_buffer(buf);
+ }
if (old_tw != curbuf->b_p_tw) {
check_colorcolumn(curwin);
}
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index fe61a2fc90..7905b29876 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -361,7 +361,7 @@ int readfile(char_u *fname, char_u *sfname, linenr_T from, linenr_T lines_to_ski
filemess(curbuf, fname, (char_u *)_(msg_is_a_directory), 0);
msg_end();
msg_scroll = msg_save;
- return FAIL;
+ return NOTDONE;
}
}
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index fc66fb5f06..4404ee7b80 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -3893,7 +3893,7 @@ void ex_display(exarg_T *eap)
msg_puts_attr("^J", attr);
n -= 2;
}
- for (p = yb->y_array[j]; *p && (n -= ptr2cells(p)) >= 0; p++) {
+ for (p = yb->y_array[j]; *p && (n -= ptr2cells(p)) >= 0; p++) { // -V1019
clen = utfc_ptr2len(p);
msg_outtrans_len(p, clen);
p += clen - 1;
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 5a10543559..41a129dba9 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -938,7 +938,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
if (mod_top != 0
&& wp->w_topline == mod_top
&& (!wp->w_lines[0].wl_valid
- || wp->w_topline <= wp->w_lines[0].wl_lnum)) {
+ || wp->w_topline == wp->w_lines[0].wl_lnum)) {
// w_topline is the first changed line and window is not scrolled,
// the scrolling from changed lines will be done further down.
} else if (wp->w_lines[0].wl_valid
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index c39546b9ea..d4005e41e8 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -2343,6 +2343,19 @@ func Test_throw_in_BufWritePre()
au! throwing
endfunc
+func Test_autocmd_in_try_block()
+ call mkdir('Xdir')
+ au BufEnter * let g:fname = expand('%')
+ try
+ edit Xdir/
+ endtry
+ call assert_match('Xdir', g:fname)
+
+ unlet g:fname
+ au! BufEnter
+ call delete('Xdir', 'rf')
+endfunc
+
func Test_autocmd_CmdWinEnter()
CheckRunVimInTerminal
" There is not cmdwin switch, so
diff --git a/src/nvim/testdir/test_display.vim b/src/nvim/testdir/test_display.vim
index 9f74d0a38a..094283a3a3 100644
--- a/src/nvim/testdir/test_display.vim
+++ b/src/nvim/testdir/test_display.vim
@@ -263,6 +263,27 @@ func Test_display_scroll_at_topline()
call StopVimInTerminal(buf)
endfunc
+func Test_display_scroll_update_visual()
+ CheckScreendump
+
+ let lines =<< trim END
+ set scrolloff=0
+ call setline(1, repeat(['foo'], 10))
+ call sign_define('foo', { 'text': '>' })
+ call sign_place(1, 'bar', 'foo', bufnr(), { 'lnum': 2 })
+ call sign_place(2, 'bar', 'foo', bufnr(), { 'lnum': 1 })
+ autocmd CursorMoved * if getcurpos()[1] == 2 | call sign_unplace('bar', { 'id': 1 }) | endif
+ END
+ call writefile(lines, 'XupdateVisual.vim')
+
+ let buf = RunVimInTerminal('-S XupdateVisual.vim', #{rows: 8, cols: 60})
+ call term_sendkeys(buf, "VG7kk")
+ call VerifyScreenDump(buf, 'Test_display_scroll_update_visual', {})
+
+ call StopVimInTerminal(buf)
+ call delete('XupdateVisual.vim')
+endfunc
+
" Test for 'eob' (EndOfBuffer) item in 'fillchars'
func Test_eob_fillchars()
" default value (skipped)
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index 14d13049d9..5457223677 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -796,101 +796,102 @@ func ReadTestProtocol(name)
endfunc
func Test_locationlist()
- enew
+ enew
- augroup testgroup
- au!
- autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
- augroup END
+ augroup testgroup
+ au!
+ autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
+ augroup END
- let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
+ let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
- let qflist = []
- for word in words
- call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
- " NOTE: problem 1:
- " intentionally not setting 'lnum' so that the quickfix entries are not
- " valid
- eval qflist->setloclist(0, ' ')
- endfor
+ let qflist = []
+ for word in words
+ call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
+ " NOTE: problem 1:
+ " intentionally not setting 'lnum' so that the quickfix entries are not
+ " valid
+ eval qflist->setloclist(0, ' ')
+ endfor
- " Test A
- lrewind
- enew
- lopen
- 4lnext
- vert split
- wincmd L
- lopen
- wincmd p
- lnext
- let fileName = expand("%")
- wincmd p
- let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
- let fileName = substitute(fileName, '\\', '/', 'g')
- let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
- call assert_equal("test://bar.txt", fileName)
- call assert_equal("test://bar.txt", locationListFileName)
+ " Test A
+ lrewind
+ enew
+ lopen
+ 4lnext
+ vert split
+ wincmd L
+ lopen
+ wincmd p
+ lnext
+ let fileName = expand("%")
+ wincmd p
+ let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
+ let fileName = substitute(fileName, '\\', '/', 'g')
+ let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
+ call assert_equal("test://bar.txt", fileName)
+ call assert_equal("test://bar.txt", locationListFileName)
- wincmd n | only
+ wincmd n | only
- " Test B:
- lrewind
- lopen
- 2
- exe "normal \<CR>"
- wincmd p
- 3
- exe "normal \<CR>"
- wincmd p
- 4
- exe "normal \<CR>"
- call assert_equal(2, winnr('$'))
- wincmd n | only
+ " Test B:
+ lrewind
+ lopen
+ 2
+ exe "normal \<CR>"
+ wincmd p
+ 3
+ exe "normal \<CR>"
+ wincmd p
+ 4
+ exe "normal \<CR>"
+ call assert_equal(2, winnr('$'))
+ wincmd n | only
- " Test C:
- lrewind
- lopen
- " Let's move the location list window to the top to check whether it (the
- " first window found) will be reused when we try to open new windows:
- wincmd K
- 2
- exe "normal \<CR>"
- wincmd p
- 3
- exe "normal \<CR>"
- wincmd p
- 4
- exe "normal \<CR>"
- 1wincmd w
- call assert_equal('quickfix', &buftype)
- 2wincmd w
- let bufferName = expand("%")
- let bufferName = substitute(bufferName, '\\', '/', 'g')
- call assert_equal('test://quux.txt', bufferName)
+ " Test C:
+ lrewind
+ lopen
+ " Let's move the location list window to the top to check whether it (the
+ " first window found) will be reused when we try to open new windows:
+ wincmd K
+ 2
+ exe "normal \<CR>"
+ wincmd p
+ 3
+ exe "normal \<CR>"
+ wincmd p
+ 4
+ exe "normal \<CR>"
+ 1wincmd w
+ call assert_equal('quickfix', &buftype)
+ 2wincmd w
+ let bufferName = expand("%")
+ let bufferName = substitute(bufferName, '\\', '/', 'g')
+ call assert_equal('test://quux.txt', bufferName)
- wincmd n | only
+ wincmd n | only
- augroup! testgroup
+ augroup! testgroup
endfunc
func Test_locationlist_curwin_was_closed()
- augroup testgroup
- au!
- autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
- augroup END
+ augroup testgroup
+ au!
+ autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
+ augroup END
- func! R(n)
- quit
- endfunc
+ func! R(n)
+ quit
+ endfunc
- new
- let q = []
- call add(q, {'filename': 'test_curwin.txt' })
- call setloclist(0, q)
- call assert_fails('lrewind', 'E924:')
+ new
+ let q = []
+ call add(q, {'filename': 'test_curwin.txt' })
+ call setloclist(0, q)
+ call assert_fails('lrewind', 'E924:')
- augroup! testgroup
+ augroup! testgroup
+ delfunc R
endfunc
func Test_locationlist_cross_tab_jump()
@@ -5489,4 +5490,45 @@ func Test_two_qf_windows()
%bw!
endfunc
+" Weird sequence of commands that caused entering a wiped-out buffer
+func Test_lopen_bwipe()
+ func R()
+ silent! tab lopen
+ e x
+ silent! lfile
+ endfunc
+
+ cal R()
+ cal R()
+ cal R()
+ bw!
+ delfunc R
+endfunc
+
+" Another sequence of commands that caused all buffers to be wiped out
+func Test_lopen_bwipe_all()
+ let lines =<< trim END
+ func R()
+ silent! tab lopen
+ e foo
+ silent! lfile
+ endfunc
+ cal R()
+ exe "norm \<C-W>\<C-V>0"
+ cal R()
+ bwipe
+
+ call writefile(['done'], 'Xresult')
+ qall!
+ END
+ call writefile(lines, 'Xscript')
+ if RunVim([], [], '--clean -n -S Xscript')
+ call assert_equal(['done'], readfile('Xresult'))
+ endif
+
+ call delete('Xscript')
+ call delete('Xresult')
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 79a6b9ed0e..a67bcf98dc 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -131,6 +131,7 @@ typedef struct {
int get_bg;
int set_underline_style;
int set_underline_color;
+ int enable_extended_keys, disable_extended_keys;
} unibi_ext;
char *space_buf;
} TUIData;
@@ -168,7 +169,7 @@ UI *tui_start(void)
ui->set_title = tui_set_title;
ui->set_icon = tui_set_icon;
ui->screenshot = tui_screenshot;
- ui->option_set= tui_option_set;
+ ui->option_set = tui_option_set;
ui->raw_line = tui_raw_line;
memset(ui->ui_ext, 0, sizeof(ui->ui_ext));
@@ -225,6 +226,8 @@ static void terminfo_start(UI *ui)
data->unibi_ext.reset_cursor_style = -1;
data->unibi_ext.get_bg = -1;
data->unibi_ext.set_underline_color = -1;
+ data->unibi_ext.enable_extended_keys = -1;
+ data->unibi_ext.disable_extended_keys = -1;
data->out_fd = STDOUT_FILENO;
data->out_isatty = os_isatty(data->out_fd);
@@ -308,6 +311,10 @@ static void terminfo_start(UI *ui)
// Enable bracketed paste
unibi_out_ext(ui, data->unibi_ext.enable_bracketed_paste);
+ // Enable extended keys (also known as 'modifyOtherKeys' or CSI u). On terminals that don't
+ // support this, this sequence is ignored.
+ unibi_out_ext(ui, data->unibi_ext.enable_extended_keys);
+
int ret;
uv_loop_init(&data->write_loop);
if (data->out_isatty) {
@@ -365,6 +372,8 @@ static void terminfo_stop(UI *ui)
unibi_out_ext(ui, data->unibi_ext.disable_bracketed_paste);
// Disable focus reporting
unibi_out_ext(ui, data->unibi_ext.disable_focus_reporting);
+ // Disable extended keys
+ unibi_out_ext(ui, data->unibi_ext.disable_extended_keys);
flush_buf(ui);
uv_tty_reset_mode();
uv_close((uv_handle_t *)&data->output_handle, NULL);
@@ -1378,7 +1387,6 @@ static void tui_screenshot(UI *ui, String path)
fclose(f);
}
-
static void tui_option_set(UI *ui, String name, Object value)
{
TUIData *data = ui->data;
@@ -1387,11 +1395,9 @@ static void tui_option_set(UI *ui, String name, Object value)
data->print_attr_id = -1;
invalidate(ui, 0, data->grid.height, 0, data->grid.width);
- }
- if (strequal(name.data, "ttimeout")) {
+ } else if (strequal(name.data, "ttimeout")) {
data->input.ttimeout = value.data.boolean;
- }
- if (strequal(name.data, "ttimeoutlen")) {
+ } else if (strequal(name.data, "ttimeoutlen")) {
data->input.ttimeoutlen = (long)value.data.integer;
}
}
@@ -1944,6 +1950,7 @@ static void augment_terminfo(TUIData *data, const char *term, long vte_version,
|| terminfo_is_term_family(term, "iTerm.app")
|| terminfo_is_term_family(term, "iTerm2.app");
bool alacritty = terminfo_is_term_family(term, "alacritty");
+ bool kitty = terminfo_is_term_family(term, "xterm-kitty");
// None of the following work over SSH; see :help TERM .
bool iterm_pretending_xterm = xterm && iterm_env;
@@ -2067,6 +2074,15 @@ static void augment_terminfo(TUIData *data, const char *term, long vte_version,
data->unibi_ext.set_underline_color = (int)unibi_add_ext_str(ut, "ext.set_underline_color",
"\x1b[58:2::%p1%d:%p2%d:%p3%dm");
}
+
+ if (!kitty) {
+ // Kitty does not support these sequences; it only supports it's own CSI > 1 u which enables the
+ // Kitty keyboard protocol
+ data->unibi_ext.enable_extended_keys = (int)unibi_add_ext_str(ut, "ext.enable_extended_keys",
+ "\x1b[>4;2m");
+ data->unibi_ext.disable_extended_keys = (int)unibi_add_ext_str(ut, "ext.disable_extended_keys",
+ "\x1b[>4;0m");
+ }
}
static void flush_buf(UI *ui)
diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c
index e723a30d32..6a7695bf72 100644
--- a/src/nvim/ui_client.c
+++ b/src/nvim/ui_client.c
@@ -151,10 +151,8 @@ void ui_client_event_grid_line(Array args)
Integer startcol = args.items[2].data.integer;
Array cells = args.items[3].data.array;
- Integer endcol, clearcol;
- // TODO(hlpr98): Accomodate other LineFlags when included in grid_line
+ // TODO(hlpr98): Accommodate other LineFlags when included in grid_line
LineFlags lineflags = 0;
- endcol = startcol;
size_t j = 0;
int cur_attr = 0;
@@ -203,8 +201,8 @@ void ui_client_event_grid_line(Array args)
}
}
- endcol = startcol + (int)j;
- clearcol = endcol + clear_width;
+ Integer endcol = startcol + (int)j;
+ Integer clearcol = endcol + clear_width;
clear_attr = cur_attr;
ui_call_raw_line(grid, row, startcol, endcol, clearcol, clear_attr, lineflags,
diff --git a/test/functional/legacy/display_spec.lua b/test/functional/legacy/display_spec.lua
index 3fbbe96947..59ba170e33 100644
--- a/test/functional/legacy/display_spec.lua
+++ b/test/functional/legacy/display_spec.lua
@@ -3,15 +3,15 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local poke_eventloop = helpers.poke_eventloop
+local exec = helpers.exec
local feed = helpers.feed
local feed_command = helpers.feed_command
describe('display', function()
- local screen
+ before_each(clear)
it('scroll when modified at topline', function()
- clear()
- screen = Screen.new(20, 4)
+ local screen = Screen.new(20, 4)
screen:attach()
screen:set_default_attr_ids({
[1] = {bold = true},
@@ -27,5 +27,35 @@ describe('display', function()
{1:-- INSERT --} |
]])
end)
+
+ it('scrolling when modified at topline in Visual mode', function()
+ local screen = Screen.new(60, 8)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {bold = true}, -- ModeMsg
+ [2] = {background = Screen.colors.LightGrey}, -- Visual
+ [3] = {background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue}, -- SignColumn
+ })
+
+ exec([[
+ set scrolloff=0
+ call setline(1, repeat(['foo'], 10))
+ call sign_define('foo', { 'text': '>' })
+ call sign_place(1, 'bar', 'foo', bufnr(), { 'lnum': 2 })
+ call sign_place(2, 'bar', 'foo', bufnr(), { 'lnum': 1 })
+ autocmd CursorMoved * if getcurpos()[1] == 2 | call sign_unplace('bar', { 'id': 1 }) | endif
+ ]])
+ feed('VG7kk')
+ screen:expect([[
+ {3: }^f{2:oo} |
+ {3: }foo |
+ {3: }foo |
+ {3: }foo |
+ {3: }foo |
+ {3: }foo |
+ {3: }foo |
+ {1:-- VISUAL LINE --} |
+ ]])
+ end)
end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 38cb54fbc6..1547f3244e 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -490,6 +490,12 @@ describe('lua stdlib', function()
eq(false, exec_lua("return vim.tbl_isempty({a=1, b=2, c=3})"))
end)
+ it('vim.tbl_get', function()
+ eq(true, exec_lua("return vim.tbl_get({ test = { nested_test = true }}, 'test', 'nested_test')"))
+ eq(NIL, exec_lua("return vim.tbl_get({}, 'missing_key')"))
+ eq(NIL, exec_lua("return vim.tbl_get({})"))
+ end)
+
it('vim.tbl_extend', function()
ok(exec_lua([[
local a = {x = 1}
diff --git a/test/functional/plugin/matchparen_spec.lua b/test/functional/plugin/matchparen_spec.lua
index 13e1283e2c..2670734c1a 100644
--- a/test/functional/plugin/matchparen_spec.lua
+++ b/test/functional/plugin/matchparen_spec.lua
@@ -27,7 +27,7 @@ describe('matchparen', function()
feed('{<cr>')
feed('}')
- -- critical part: up + cr should result in an empty line inbetween the
+ -- critical part: up + cr should result in an empty line in between the
-- brackets... if the bug is there, the empty line will be before the '{'
feed('<up>')
feed('<cr>')
diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua
index 3e0e15c2b7..bc52696418 100644
--- a/test/functional/ui/fold_spec.lua
+++ b/test/functional/ui/fold_spec.lua
@@ -1672,7 +1672,7 @@ describe("folded lines", function()
end
-- relax the maximum fdc thus fdc should expand to
- -- accomodate the current number of folds
+ -- accommodate the current number of folds
command("set foldcolumn=auto:4")
if multigrid then
screen:expect([[
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index 8a8720fca3..6d02a73d14 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -151,8 +151,8 @@ set(MSGPACK_URL https://github.com/msgpack/msgpack-c/releases/download/cpp-3.0.0
set(MSGPACK_SHA256 bfbb71b7c02f806393bc3cbc491b40523b89e64f83860c58e3e54af47de176e4)
# https://github.com/LuaJIT/LuaJIT/tree/v2.1
-set(LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/1d20f33d2905db55fb7191076bbac10f570f9175.tar.gz)
-set(LUAJIT_SHA256 4b6e2fc726ed8bf51fe461d90db9fffbc5c894bbdc862a67d17a70190f1fb07f)
+set(LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/e2c312e0deb874aa5fa8ce502c08d87deb38e82f.tar.gz)
+set(LUAJIT_SHA256 bff4764c19466def90667d2f7fcbd0781b8e62476b12105868f8e44babd03f8e)
set(LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz)
set(LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333)