aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.github/scripts/install_deps.sh6
-rw-r--r--.github/workflows/test.yml4
-rw-r--r--runtime/compiler/bdf.vim10
-rw-r--r--runtime/compiler/mcs.vim15
-rw-r--r--runtime/compiler/modelsim_vcom.vim6
-rw-r--r--runtime/compiler/powershell.vim7
-rw-r--r--runtime/compiler/tex.vim6
-rw-r--r--runtime/doc/lua.txt19
-rw-r--r--runtime/doc/news.txt3
-rw-r--r--runtime/doc/options.txt3
-rw-r--r--runtime/doc/provider.txt2
-rw-r--r--runtime/doc/syntax.txt8
-rw-r--r--runtime/lua/vim/_editor.lua15
-rw-r--r--runtime/lua/vim/_meta/options.lua3
-rw-r--r--runtime/lua/vim/fs.lua59
-rw-r--r--runtime/lua/vim/lsp/buf.lua7
-rw-r--r--runtime/syntax/pamconf.vim13
-rw-r--r--runtime/syntax/sshconfig.vim62
-rw-r--r--runtime/syntax/sshdconfig.vim55
-rw-r--r--src/klib/kvec.h17
-rw-r--r--src/nvim/api/vim.c6
-rw-r--r--src/nvim/autocmd.c10
-rw-r--r--src/nvim/autocmd.h11
-rw-r--r--src/nvim/buffer.c6
-rw-r--r--src/nvim/buffer_defs.h13
-rw-r--r--src/nvim/change.c13
-rw-r--r--src/nvim/edit.c5
-rw-r--r--src/nvim/eval/funcs.c2
-rw-r--r--src/nvim/ex_cmds.c2
-rw-r--r--src/nvim/ex_docmd.c4
-rw-r--r--src/nvim/fileio.c8
-rw-r--r--src/nvim/getchar.c88
-rw-r--r--src/nvim/globals.h2
-rw-r--r--src/nvim/highlight_group.c21
-rw-r--r--src/nvim/highlight_group.h2
-rw-r--r--src/nvim/lua/executor.c9
-rw-r--r--src/nvim/message.c4
-rw-r--r--src/nvim/normal.c2
-rw-r--r--src/nvim/option.c2
-rw-r--r--src/nvim/options.lua3
-rw-r--r--src/nvim/os/input.c4
-rw-r--r--src/nvim/quickfix.c4
-rw-r--r--src/nvim/runtime.c2
-rw-r--r--src/nvim/terminal.c5
-rw-r--r--test/functional/api/vim_spec.lua15
-rw-r--r--test/functional/autocmd/textchanged_spec.lua26
-rw-r--r--test/functional/core/channels_spec.lua3
-rw-r--r--test/functional/core/job_spec.lua10
-rw-r--r--test/functional/editor/meta_key_spec.lua25
-rw-r--r--test/functional/ex_cmds/arg_spec.lua3
-rw-r--r--test/functional/ex_cmds/edit_spec.lua3
-rw-r--r--test/functional/ex_cmds/verbose_spec.lua72
-rw-r--r--test/functional/legacy/normal_spec.lua93
-rw-r--r--test/functional/lua/buffer_updates_spec.lua67
-rw-r--r--test/functional/lua/fs_spec.lua77
-rw-r--r--test/functional/lua/vim_spec.lua58
-rw-r--r--test/functional/terminal/mouse_spec.lua6
-rw-r--r--test/functional/vimscript/reltime_spec.lua5
-rw-r--r--test/functional/vimscript/server_spec.lua4
-rw-r--r--test/old/testdir/test_autocmd.vim97
-rw-r--r--test/old/testdir/test_conceal.vim1
-rw-r--r--test/old/testdir/test_normal.vim23
-rw-r--r--test/old/testdir/test_perl.vim3
-rw-r--r--test/old/testdir/test_registers.vim52
-rw-r--r--test/old/testdir/test_scroll_opt.vim8
-rw-r--r--test/old/testdir/test_utf8.vim51
-rw-r--r--test/unit/eval/typval_spec.lua2
67 files changed, 901 insertions, 351 deletions
diff --git a/.github/scripts/install_deps.sh b/.github/scripts/install_deps.sh
index 2b8335f192..66f418eb10 100755
--- a/.github/scripts/install_deps.sh
+++ b/.github/scripts/install_deps.sh
@@ -31,11 +31,17 @@ if [[ $os == Linux ]]; then
if [[ -n $TEST ]]; then
sudo apt-get install -y locales-all cpanminus attr libattr1-dev gdb fswatch
+
+ # Use default CC to avoid compilation problems when installing Python modules
+ CC=cc python3 -m pip -q install --user --upgrade pynvim
fi
elif [[ $os == Darwin ]]; then
brew update --quiet
brew install ninja
if [[ -n $TEST ]]; then
brew install cpanminus fswatch
+
+ # Use default CC to avoid compilation problems when installing Python modules
+ CC=cc python3 -m pip -q install --user --upgrade --break-system-packages pynvim
fi
fi
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 622304512e..d7af975748 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -134,10 +134,6 @@ jobs:
- if: ${{ matrix.test != 'unittest' }}
name: Set up interpreter packages
run: |
- # Use default CC to avoid compilation problems when installing Python modules.
- echo "Install neovim module for Python."
- CC=cc python3 -m pip -q install --user --upgrade pynvim
-
echo "Install neovim RubyGem."
gem install --no-document --bindir "$BIN_DIR" --user-install --pre neovim
diff --git a/runtime/compiler/bdf.vim b/runtime/compiler/bdf.vim
index b062e847aa..7e08cdddaa 100644
--- a/runtime/compiler/bdf.vim
+++ b/runtime/compiler/bdf.vim
@@ -1,7 +1,8 @@
" Vim compiler file
" Compiler: BDF to PCF Conversion
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2006-04-19
+" Contributors: Enno Nagel
+" Last Change: 2024 Mar 29
if exists("current_compiler")
finish
@@ -11,9 +12,12 @@ let current_compiler = "bdf"
let s:cpo_save = &cpo
set cpo-=C
-setlocal makeprg=bdftopcf\ $*
+if exists(":CompilerSet") != 2 " Older Vim always used :setlocal
+ command -nargs=* CompilerSet setlocal <args>
+endif
-setlocal errorformat=%ABDF\ %trror\ on\ line\ %l:\ %m,
+CompilerSet makeprg=bdftopcf\ $*
+CompilerSet errorformat=%ABDF\ %trror\ on\ line\ %l:\ %m,
\%-Z%p^,
\%Cbdftopcf:\ bdf\ input\\,\ %f\\,\ corrupt,
\%-G%.%#
diff --git a/runtime/compiler/mcs.vim b/runtime/compiler/mcs.vim
index c606586870..94a1848d4a 100644
--- a/runtime/compiler/mcs.vim
+++ b/runtime/compiler/mcs.vim
@@ -1,8 +1,8 @@
" Vim compiler file
-" Compiler: Mono C# Compiler
-" Maintainer: Jarek Sobiecki <harijari@go2.pl>
-" Last Updated By: Peter Collingbourne
-" Latest Revision: 2012 Jul 19
+" Compiler: Mono C# Compiler
+" Maintainer: Jarek Sobiecki <harijari@go2.pl>
+" Contributors: Peter Collingbourne and Enno Nagel
+" Last Change: 2024 Mar 29
if exists("current_compiler")
finish
@@ -12,7 +12,12 @@ let current_compiler = "mcs"
let s:cpo_save = &cpo
set cpo-=C
-setlocal errorformat=
+if exists(":CompilerSet") != 2 " Older Vim always used :setlocal
+ command -nargs=* CompilerSet setlocal <args>
+endif
+
+CompilerSet makeprg=mcs
+CompilerSet errorformat=
\%D%.%#Project\ \"%f/%[%^/\"]%#\"%.%#,
\%X%.%#Done\ building\ project\ \"%f/%[%^/\"]%#\"%.%#,
\%-G%\\s%.%#,
diff --git a/runtime/compiler/modelsim_vcom.vim b/runtime/compiler/modelsim_vcom.vim
index 6aa1bde0b3..184b403996 100644
--- a/runtime/compiler/modelsim_vcom.vim
+++ b/runtime/compiler/modelsim_vcom.vim
@@ -1,7 +1,8 @@
" Vim Compiler File
" Compiler: Modelsim Vcom
" Maintainer: Paul Baleme <pbaleme@mail.com>
-" Last Change: September 8, 2003
+" Contributors: Enno Nagel
+" Last Change: 2024 Mar 29
" Thanks to: allanherriman@hotmail.com
if exists("current_compiler")
@@ -13,8 +14,9 @@ if exists(":CompilerSet") != 2 " older Vim always used :setlocal
command -nargs=* CompilerSet setlocal <args>
endif
-"setlocal errorformat=\*\*\ %tRROR:\ %f(%l):\ %m,%tRROR:\ %f(%l):\ %m,%tARNING\[%*[0-9]\]:\ %f(%l):\ %m,\*\*\ %tRROR:\ %m,%tRROR:\ %m,%tARNING\[%*[0-9]\]:\ %m
+CompilerSet makeprg=vcom
+"setlocal errorformat=\*\*\ %tRROR:\ %f(%l):\ %m,%tRROR:\ %f(%l):\ %m,%tARNING\[%*[0-9]\]:\ %f(%l):\ %m,\*\*\ %tRROR:\ %m,%tRROR:\ %m,%tARNING\[%*[0-9]\]:\ %m
"setlocal errorformat=%tRROR:\ %f(%l):\ %m,%tARNING\[%*[0-9]\]:\ %m
CompilerSet errorformat=\*\*\ %tRROR:\ %f(%l):\ %m,\*\*\ %tRROR:\ %m,\*\*\ %tARNING:\ %m,\*\*\ %tOTE:\ %m,%tRROR:\ %f(%l):\ %m,%tARNING\[%*[0-9]\]:\ %f(%l):\ %m,%tRROR:\ %m,%tARNING\[%*[0-9]\]:\ %m
diff --git a/runtime/compiler/powershell.vim b/runtime/compiler/powershell.vim
index 45d5ec2191..445a2f6d97 100644
--- a/runtime/compiler/powershell.vim
+++ b/runtime/compiler/powershell.vim
@@ -1,7 +1,8 @@
" Vim compiler file
" Compiler: powershell
" URL: https://github.com/PProvost/vim-ps1
-" Last Change: 2020 Mar 30
+" Contributors: Enno Nagel
+" Last Change: 2024 Mar 29
if exists("current_compiler")
finish
@@ -37,7 +38,7 @@ let g:ps1_efm_show_error_categories = get(g:, 'ps1_efm_show_error_categories', 0
" Use absolute path because powershell requires explicit relative paths
" (./file.ps1 is okay, but # expands to file.ps1)
-let &l:makeprg = g:ps1_makeprg_cmd .' %:p:S'
+let makeprg = g:ps1_makeprg_cmd .. ' %:p:S'
" Parse file, line, char from callstacks:
" Write-Ouput : The term 'Write-Ouput' is not recognized as the name of a
@@ -50,6 +51,8 @@ let &l:makeprg = g:ps1_makeprg_cmd .' %:p:S'
" + CategoryInfo : ObjectNotFound: (Write-Ouput:String) [], CommandNotFoundException
" + FullyQualifiedErrorId : CommandNotFoundException
+execute 'CompilerSet makeprg=' .. escape(makeprg, ' ')
+
" Showing error in context with underlining.
CompilerSet errorformat=%+G+%m
" Error summary.
diff --git a/runtime/compiler/tex.vim b/runtime/compiler/tex.vim
index 65e15cf6e2..0925d17680 100644
--- a/runtime/compiler/tex.vim
+++ b/runtime/compiler/tex.vim
@@ -1,7 +1,8 @@
" Vim compiler file
" Compiler: TeX
" Maintainer: Artem Chuprina <ran@ran.pp.ru>
-" Last Change: 2012 Apr 30
+" Contributors: Enno Nagel
+" Last Change: 2024 Mar 29
if exists("current_compiler")
finish
@@ -27,7 +28,8 @@ if exists('b:tex_ignore_makefile') || exists('g:tex_ignore_makefile') ||
else
let current_compiler = "latex"
endif
- let &l:makeprg=current_compiler.' -interaction=nonstopmode'
+ let makeprg=current_compiler .. ' -interaction=nonstopmode'
+ execute 'CompilerSet makeprg=' .. escape(makeprg, ' ')
else
let current_compiler = 'make'
endif
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index b9bc73e0b8..d967e2b313 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -1640,12 +1640,14 @@ vim.on_key({fn}, {ns_id}) *vim.on_key()*
Note: ~
• {fn} will be removed on error.
• {fn} will not be cleared by |nvim_buf_clear_namespace()|
- • {fn} will receive the keys after mappings have been evaluated
Parameters: ~
- • {fn} (`fun(key: string)?`) Function invoked on every key press.
- |i_CTRL-V| Passing in nil when {ns_id} is specified removes
- the callback associated with namespace {ns_id}.
+ • {fn} (`fun(key: string, typed: string)?`) Function invoked on
+ every key press. |i_CTRL-V| {key} is the key after mappings
+ have been applied, and {typed} is the key(s) before mappings
+ are applied, which may be empty if {key} is produced by
+ non-typed keys. When {fn} is nil and {ns_id} is specified,
+ the callback associated with namespace {ns_id} is removed.
• {ns_id} (`integer?`) Namespace ID. If nil or 0, generates and returns
a new |nvim_create_namespace()| id.
@@ -2954,13 +2956,14 @@ vim.fs.joinpath({...}) *vim.fs.joinpath()*
vim.fs.normalize({path}, {opts}) *vim.fs.normalize()*
Normalize a path to a standard format. A tilde (~) character at the
- beginning of the path is expanded to the user's home directory and any
- backslash (\) characters are converted to forward slashes (/). Environment
- variables are also expanded.
+ beginning of the path is expanded to the user's home directory and
+ environment variables are also expanded.
+
+ On Windows, backslash (\) characters are converted to forward slashes (/).
Examples: >lua
vim.fs.normalize('C:\\\\Users\\\\jdoe')
- -- 'C:/Users/jdoe'
+ -- On Windows: 'C:/Users/jdoe'
vim.fs.normalize('~/src/neovim')
-- '/home/jdoe/src/neovim'
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 1aee5c656b..e39cf95da9 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -354,6 +354,9 @@ The following changes to existing APIs or features add new behavior.
• |vim.region()| can use a string accepted by |getpos()| as position.
+• |vim.on_key()| callbacks receive a second argument for keys typed before
+ mappings are applied.
+
• |vim.diagnostic.config()| now accepts a function for the virtual_text.prefix
option, which allows for rendering e.g., diagnostic severities differently.
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index b0583d306d..54333ee85d 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -5693,8 +5693,7 @@ A jump table for the options with a short description can be found at |Q_op|.
highlighted with |hl-NonText|.
You may also want to add "lastline" to the 'display' option to show as
much of the last line as possible.
- NOTE: only partly implemented, currently works with CTRL-E, CTRL-Y,
- CTRL-D, CTRL-U, CTRL-F, CTRL-B and scrolling with the mouse.
+ NOTE: partly implemented, doesn't work yet for |gj| and |gk|.
*'softtabstop'* *'sts'*
'softtabstop' 'sts' number (default 0)
diff --git a/runtime/doc/provider.txt b/runtime/doc/provider.txt
index b8182347f8..a39f4bc5d7 100644
--- a/runtime/doc/provider.txt
+++ b/runtime/doc/provider.txt
@@ -185,7 +185,7 @@ See 'clipboard' for details and options.
The presence of a working clipboard tool implicitly enables the '+' and "*"
registers. Nvim looks for these clipboard tools, in order of priority:
- - |g:clipboard|
+ - |g:clipboard| (unless unset or `false`)
- pbcopy, pbpaste (macOS)
- wl-copy, wl-paste (if $WAYLAND_DISPLAY is set)
- waycopy, waypaste (if $WAYLAND_DISPLAY is set)
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index 4b99fbface..5e95e00e45 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -4776,11 +4776,11 @@ guisp={color-name} *guisp*
Colors which define Nvim's default color scheme:
NvimDarkBlue NvimLightBlue
NvimDarkCyan NvimLightCyan
+ NvimDarkGray1 NvimLightGray1
+ NvimDarkGray2 NvimLightGray2
+ NvimDarkGray3 NvimLightGray3
+ NvimDarkGray4 NvimLightGray4
NvimDarkGreen NvimLightGreen
- NvimDarkGrey1 NvimLightGrey1
- NvimDarkGrey2 NvimLightGrey2
- NvimDarkGrey3 NvimLightGrey3
- NvimDarkGrey4 NvimLightGrey4
NvimDarkMagenta NvimLightMagenta
NvimDarkRed NvimLightRed
NvimDarkYellow NvimLightYellow
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index f527fc194c..18f6cfa4ba 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -654,11 +654,14 @@ local on_key_cbs = {} --- @type table<integer,function>
---
---@note {fn} will be removed on error.
---@note {fn} will not be cleared by |nvim_buf_clear_namespace()|
----@note {fn} will receive the keys after mappings have been evaluated
---
----@param fn fun(key: string)? Function invoked on every key press. |i_CTRL-V|
---- Passing in nil when {ns_id} is specified removes the
---- callback associated with namespace {ns_id}.
+---@param fn fun(key: string, typed: string)?
+--- Function invoked on every key press. |i_CTRL-V|
+--- {key} is the key after mappings have been applied, and
+--- {typed} is the key(s) before mappings are applied, which
+--- may be empty if {key} is produced by non-typed keys.
+--- When {fn} is nil and {ns_id} is specified, the callback
+--- associated with namespace {ns_id} is removed.
---@param ns_id integer? Namespace ID. If nil or 0, generates and returns a
--- new |nvim_create_namespace()| id.
---
@@ -684,11 +687,11 @@ end
--- Executes the on_key callbacks.
---@private
-function vim._on_key(char)
+function vim._on_key(buf, typed_buf)
local failed_ns_ids = {}
local failed_messages = {}
for k, v in pairs(on_key_cbs) do
- local ok, err_msg = pcall(v, char)
+ local ok, err_msg = pcall(v, buf, typed_buf)
if not ok then
vim.on_key(nil, k)
table.insert(failed_ns_ids, k)
diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua
index adc42f9659..5e40851457 100644
--- a/runtime/lua/vim/_meta/options.lua
+++ b/runtime/lua/vim/_meta/options.lua
@@ -6075,8 +6075,7 @@ vim.go.sta = vim.go.smarttab
--- highlighted with `hl-NonText`.
--- You may also want to add "lastline" to the 'display' option to show as
--- much of the last line as possible.
---- NOTE: only partly implemented, currently works with CTRL-E, CTRL-Y,
---- CTRL-D, CTRL-U, CTRL-F, CTRL-B and scrolling with the mouse.
+--- NOTE: partly implemented, doesn't work yet for `gj` and `gk`.
---
--- @type boolean
vim.o.smoothscroll = false
diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua
index f9fe122f01..ad0d914ea2 100644
--- a/runtime/lua/vim/fs.lua
+++ b/runtime/lua/vim/fs.lua
@@ -1,6 +1,7 @@
local M = {}
local iswin = vim.uv.os_uname().sysname == 'Windows_NT'
+local os_sep = iswin and '\\' or '/'
--- Iterate over all the parents of the given path.
---
@@ -47,19 +48,23 @@ function M.dirname(file)
return nil
end
vim.validate({ file = { file, 's' } })
- if iswin and file:match('^%w:[\\/]?$') then
- return (file:gsub('\\', '/'))
- elseif not file:match('[\\/]') then
+ if iswin then
+ file = file:gsub(os_sep, '/') --[[@as string]]
+ if file:match('^%w:/?$') then
+ return file
+ end
+ end
+ if not file:match('/') then
return '.'
elseif file == '/' or file:match('^/[^/]+$') then
return '/'
end
---@type string
- local dir = file:match('[/\\]$') and file:sub(1, #file - 1) or file:match('^([/\\]?.+)[/\\]')
+ local dir = file:match('/$') and file:sub(1, #file - 1) or file:match('^(/?.+)/')
if iswin and dir:match('^%w:$') then
return dir .. '/'
end
- return (dir:gsub('\\', '/'))
+ return dir
end
--- Return the basename of the given path
@@ -72,10 +77,13 @@ function M.basename(file)
return nil
end
vim.validate({ file = { file, 's' } })
- if iswin and file:match('^%w:[\\/]?$') then
- return ''
+ if iswin then
+ file = file:gsub(os_sep, '/') --[[@as string]]
+ if file:match('^%w:/?$') then
+ return ''
+ end
end
- return file:match('[/\\]$') and '' or (file:match('[^\\/]*$'):gsub('\\', '/'))
+ return file:match('/$') and '' or (file:match('[^/]*$'))
end
--- Concatenate directories and/or file paths into a single path with normalization
@@ -334,15 +342,16 @@ end
--- @field expand_env boolean
--- Normalize a path to a standard format. A tilde (~) character at the
---- beginning of the path is expanded to the user's home directory and any
---- backslash (\) characters are converted to forward slashes (/). Environment
---- variables are also expanded.
+--- beginning of the path is expanded to the user's home directory and
+--- environment variables are also expanded.
+---
+--- On Windows, backslash (\) characters are converted to forward slashes (/).
---
--- Examples:
---
--- ```lua
--- vim.fs.normalize('C:\\\\Users\\\\jdoe')
---- -- 'C:/Users/jdoe'
+--- -- On Windows: 'C:/Users/jdoe'
---
--- vim.fs.normalize('~/src/neovim')
--- -- '/home/jdoe/src/neovim'
@@ -362,23 +371,41 @@ function M.normalize(path, opts)
expand_env = { opts.expand_env, { 'boolean' }, true },
})
- if path:sub(1, 1) == '~' then
+ -- Expand ~ to users home directory
+ if vim.startswith(path, '~') then
local home = vim.uv.os_homedir() or '~'
- if home:sub(-1) == '\\' or home:sub(-1) == '/' then
+ if home:sub(-1) == os_sep then
home = home:sub(1, -2)
end
path = home .. path:sub(2)
end
+ -- Expand environment variables if `opts.expand_env` isn't `false`
if opts.expand_env == nil or opts.expand_env then
path = path:gsub('%$([%w_]+)', vim.uv.os_getenv)
end
- path = path:gsub('\\', '/'):gsub('/+', '/')
+ -- Convert path separator to `/`
+ path = path:gsub(os_sep, '/')
+
+ -- Don't modify leading double slash as those have implementation-defined behavior according to
+ -- POSIX. They are also valid UNC paths. Three or more leading slashes are however collapsed to
+ -- a single slash.
+ if vim.startswith(path, '//') and not vim.startswith(path, '///') then
+ path = '/' .. path:gsub('/+', '/')
+ else
+ path = path:gsub('/+', '/')
+ end
+
+ -- Ensure last slash is not truncated from root drive on Windows
if iswin and path:match('^%w:/$') then
return path
end
- return (path:gsub('(.)/$', '%1'))
+
+ -- Remove trailing slashes
+ path = path:gsub('(.)/$', '%1')
+
+ return path
end
return M
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 50121f30b2..43f52b8116 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -461,7 +461,14 @@ local function call_hierarchy(method)
vim.notify(err.message, vim.log.levels.WARN)
return
end
+ if not result then
+ vim.notify('No item resolved', vim.log.levels.WARN)
+ return
+ end
local call_hierarchy_item = pick_call_hierarchy_item(result)
+ if not call_hierarchy_item then
+ return
+ end
local client = vim.lsp.get_client_by_id(ctx.client_id)
if client then
client.request(method, { item = call_hierarchy_item }, nil, ctx.bufnr)
diff --git a/runtime/syntax/pamconf.vim b/runtime/syntax/pamconf.vim
index 29132848a9..1b5f901348 100644
--- a/runtime/syntax/pamconf.vim
+++ b/runtime/syntax/pamconf.vim
@@ -1,9 +1,9 @@
" Vim syntax file
" Language: pam(8) configuration file
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2020/08/04
+" Latest Change: 2024/03/31
" Changes By: Haochen Tong
-
+" Vim Project for the @include syntax
if exists("b:current_syntax")
finish
@@ -23,6 +23,13 @@ syn match pamconfType '-\?[[:alpha:]]\+'
syn keyword pamconfTypeKeyword contained account auth password session
+" The @include syntax is Debian specific
+syn match pamconfInclude '^@include'
+ \ nextgroup=pamconfIncludeFile
+ \ skipwhite
+
+syn match pamconfIncludeFile '\f\+$'
+
if s:has_service_field
syn match pamconfService '^[[:graph:]]\+'
\ nextgroup=pamconfType,
@@ -124,6 +131,8 @@ hi def link pamconfMPath String
hi def link pamconfMPathLineCont pamconfServiceLineCont
hi def link pamconfArgs Normal
hi def link pamconfArgsLineCont pamconfServiceLineCont
+hi def link pamconfInclude Include
+hi def link pamconfIncludeFile Include
let b:current_syntax = "pamconf"
diff --git a/runtime/syntax/sshconfig.vim b/runtime/syntax/sshconfig.vim
index 750289d83e..99e10fd1ee 100644
--- a/runtime/syntax/sshconfig.vim
+++ b/runtime/syntax/sshconfig.vim
@@ -63,8 +63,7 @@ syn keyword sshconfigMAC hmac-sha2-256
syn keyword sshconfigMAC hmac-sha2-512
syn keyword sshconfigMAC hmac-md5
syn keyword sshconfigMAC hmac-md5-96
-syn keyword sshconfigMAC hmac-ripemd160
-syn match sshconfigMAC "\<hmac-ripemd160@openssh\.com\>"
+syn match sshconfigMAC "\<hmac-ripemd160\%(@openssh\.com\)\?\>"
syn match sshconfigMAC "\<umac-64@openssh\.com\>"
syn match sshconfigMAC "\<umac-128@openssh\.com\>"
syn match sshconfigMAC "\<hmac-sha1-etm@openssh\.com\>"
@@ -107,33 +106,35 @@ syn keyword sshconfigSysLogFacility DAEMON USER AUTH AUTHPRIV LOCAL0 LOCAL1
syn keyword sshconfigSysLogFacility LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7
syn keyword sshconfigAddressFamily inet inet6
-syn match sshconfigIPQoS "af1[123]"
-syn match sshconfigIPQoS "af2[123]"
-syn match sshconfigIPQoS "af3[123]"
-syn match sshconfigIPQoS "af4[123]"
-syn match sshconfigIPQoS "cs[0-7]"
-syn keyword sshconfigIPQoS ef lowdelay throughput reliability
+syn match sshconfigIPQoS "\<af[1-4][1-3]\>"
+syn match sshconfigIPQoS "\<cs[0-7]\>"
+syn keyword sshconfigIPQoS ef le lowdelay throughput reliability
syn keyword sshconfigKbdInteractive bsdauth pam skey
syn keyword sshconfigKexAlgo diffie-hellman-group1-sha1
syn keyword sshconfigKexAlgo diffie-hellman-group14-sha1
syn keyword sshconfigKexAlgo diffie-hellman-group-exchange-sha1
syn keyword sshconfigKexAlgo diffie-hellman-group-exchange-sha256
+syn keyword sshconfigKexAlgo diffie-hellman-group16-sha512
+syn keyword sshconfigKexAlgo diffie-hellman-group18-sha512
+syn keyword sshconfigKexAlgo diffie-hellman-group14-sha256
syn keyword sshconfigKexAlgo ecdh-sha2-nistp256
syn keyword sshconfigKexAlgo ecdh-sha2-nistp384
syn keyword sshconfigKexAlgo ecdh-sha2-nistp521
-syn match sshconfigKexAlgo "\<curve25519-sha256@libssh\.org\>"
+syn match sshconfigKexAlgo "\<curve25519-sha256\%(@libssh\.org\)\?\>"
+syn match sshconfigKexAlgo "\<sntrup761x25519-sha512@openssh\.com\>"
syn keyword sshconfigTunnel point-to-point ethernet
-syn match sshconfigVar "%[rhplLdun]\>"
+syn match sshconfigVar "%[CdfHhIijKkLlnprTtu]\>"
+syn match sshconfigVar "%%"
syn match sshconfigSpecial "[*?]"
-syn match sshconfigNumber "\d\+"
+syn match sshconfigNumber "\<\d\+\>"
syn match sshconfigHostPort "\<\(\d\{1,3}\.\)\{3}\d\{1,3}\(:\d\+\)\?\>"
syn match sshconfigHostPort "\<\([-a-zA-Z0-9]\+\.\)\+[-a-zA-Z0-9]\{2,}\(:\d\+\)\?\>"
syn match sshconfigHostPort "\<\(\x\{,4}:\)\+\x\{,4}[:/]\d\+\>"
-syn match sshconfigHostPort "\(Host \)\@<=.\+"
-syn match sshconfigHostPort "\(HostName \)\@<=.\+"
+syn match sshconfigHostPort "\<\c\(Host \+\)\@<=.\+"
+syn match sshconfigHostPort "\<\c\(Hostname \+\)\@<=.\+"
" case off
syn case ignore
@@ -142,10 +143,10 @@ syn case ignore
" Keywords
syn keyword sshconfigHostSect Host
-syn keyword sshconfigMatch canonical final exec host originalhost user localuser all
+syn keyword sshconfigMatch canonical final exec localnetwork host originalhost tagged user localuser all
-syn keyword sshconfigKeyword AddressFamily
syn keyword sshconfigKeyword AddKeysToAgent
+syn keyword sshconfigKeyword AddressFamily
syn keyword sshconfigKeyword BatchMode
syn keyword sshconfigKeyword BindAddress
syn keyword sshconfigKeyword BindInterface
@@ -157,16 +158,18 @@ syn keyword sshconfigKeyword CanonicalizePermittedCNAMEs
syn keyword sshconfigKeyword CASignatureAlgorithms
syn keyword sshconfigKeyword CertificateFile
syn keyword sshconfigKeyword ChallengeResponseAuthentication
+syn keyword sshconfigKeyword ChannelTimeout
syn keyword sshconfigKeyword CheckHostIP
syn keyword sshconfigKeyword Ciphers
syn keyword sshconfigKeyword ClearAllForwardings
syn keyword sshconfigKeyword Compression
-syn keyword sshconfigKeyword ConnectTimeout
syn keyword sshconfigKeyword ConnectionAttempts
+syn keyword sshconfigKeyword ConnectTimeout
syn keyword sshconfigKeyword ControlMaster
syn keyword sshconfigKeyword ControlPath
syn keyword sshconfigKeyword ControlPersist
syn keyword sshconfigKeyword DynamicForward
+syn keyword sshconfigKeyword EnableEscapeCommandline
syn keyword sshconfigKeyword EnableSSHKeysign
syn keyword sshconfigKeyword EscapeChar
syn keyword sshconfigKeyword ExitOnForwardFailure
@@ -176,18 +179,17 @@ syn keyword sshconfigKeyword ForwardAgent
syn keyword sshconfigKeyword ForwardX11
syn keyword sshconfigKeyword ForwardX11Timeout
syn keyword sshconfigKeyword ForwardX11Trusted
-syn keyword sshconfigKeyword GSSAPIAuthentication
-syn keyword sshconfigKeyword GSSAPIDelegateCredentials
syn keyword sshconfigKeyword GatewayPorts
syn keyword sshconfigKeyword GlobalKnownHostsFile
+syn keyword sshconfigKeyword GSSAPIAuthentication
+syn keyword sshconfigKeyword GSSAPIDelegateCredentials
syn keyword sshconfigKeyword HashKnownHosts
-syn keyword sshconfigKeyword HostKeyAlgorithms
-syn keyword sshconfigKeyword HostKeyAlias
-syn keyword sshconfigKeyword HostName
-syn keyword sshconfigKeyword HostbasedAuthentication
syn keyword sshconfigKeyword HostbasedAcceptedAlgorithms
+syn keyword sshconfigKeyword HostbasedAuthentication
syn keyword sshconfigKeyword HostbasedKeyTypes
-syn keyword sshconfigKeyword IPQoS
+syn keyword sshconfigKeyword HostKeyAlgorithms
+syn keyword sshconfigKeyword HostKeyAlias
+syn keyword sshconfigKeyword Hostname
syn keyword sshconfigKeyword IdentitiesOnly
syn keyword sshconfigKeyword IdentityAgent
syn keyword sshconfigKeyword IdentityFile
@@ -206,15 +208,16 @@ syn keyword sshconfigKeyword MACs
syn keyword sshconfigKeyword Match
syn keyword sshconfigKeyword NoHostAuthenticationForLocalhost
syn keyword sshconfigKeyword NumberOfPasswordPrompts
-syn keyword sshconfigKeyword PKCS11Provider
+syn keyword sshconfigKeyword ObscureKeystrokeTiming
syn keyword sshconfigKeyword PasswordAuthentication
syn keyword sshconfigKeyword PermitLocalCommand
syn keyword sshconfigKeyword PermitRemoteOpen
+syn keyword sshconfigKeyword PKCS11Provider
syn keyword sshconfigKeyword Port
syn keyword sshconfigKeyword PreferredAuthentications
syn keyword sshconfigKeyword ProxyCommand
syn keyword sshconfigKeyword ProxyJump
-syn keyword sshconfigKeyword ProxyUseFDPass
+syn keyword sshconfigKeyword ProxyUseFdpass
syn keyword sshconfigKeyword PubkeyAcceptedAlgorithms
syn keyword sshconfigKeyword PubkeyAcceptedKeyTypes
syn keyword sshconfigKeyword PubkeyAuthentication
@@ -229,18 +232,19 @@ syn keyword sshconfigKeyword SendEnv
syn keyword sshconfigKeyword ServerAliveCountMax
syn keyword sshconfigKeyword ServerAliveInterval
syn keyword sshconfigKeyword SessionType
-syn keyword sshconfigKeyword SmartcardDevice
syn keyword sshconfigKeyword SetEnv
+syn keyword sshconfigKeyword SmartcardDevice
syn keyword sshconfigKeyword StdinNull
syn keyword sshconfigKeyword StreamLocalBindMask
syn keyword sshconfigKeyword StreamLocalBindUnlink
syn keyword sshconfigKeyword StrictHostKeyChecking
syn keyword sshconfigKeyword SyslogFacility
+syn keyword sshconfigKeyword Tag
syn keyword sshconfigKeyword TCPKeepAlive
syn keyword sshconfigKeyword Tunnel
syn keyword sshconfigKeyword TunnelDevice
-syn keyword sshconfigKeyword UseBlacklistedKeys
syn keyword sshconfigKeyword UpdateHostKeys
+syn keyword sshconfigKeyword UseBlacklistedKeys
syn keyword sshconfigKeyword User
syn keyword sshconfigKeyword UserKnownHostsFile
syn keyword sshconfigKeyword VerifyHostKeyDNS
@@ -268,9 +272,9 @@ syn keyword sshconfigDeprecated UsePrivilegedPort
hi def link sshconfigComment Comment
hi def link sshconfigTodo Todo
hi def link sshconfigHostPort sshconfigConstant
-hi def link sshconfigNumber sshconfigConstant
+hi def link sshconfigNumber Number
hi def link sshconfigConstant Constant
-hi def link sshconfigYesNo sshconfigEnum
+hi def link sshconfigYesNo Boolean
hi def link sshconfigCipher sshconfigDeprecated
hi def link sshconfigCiphers sshconfigEnum
hi def link sshconfigMAC sshconfigEnum
diff --git a/runtime/syntax/sshdconfig.vim b/runtime/syntax/sshdconfig.vim
index c0d9c3f598..8b539d907b 100644
--- a/runtime/syntax/sshdconfig.vim
+++ b/runtime/syntax/sshdconfig.vim
@@ -64,8 +64,7 @@ syn keyword sshdconfigMAC hmac-sha2-256
syn keyword sshdconfigMAC hmac-sha2-512
syn keyword sshdconfigMAC hmac-md5
syn keyword sshdconfigMAC hmac-md5-96
-syn keyword sshdconfigMAC hmac-ripemd160
-syn match sshdconfigMAC "\<hmac-ripemd160@openssh\.com\>"
+syn match sshdconfigMAC "\<hmac-ripemd160\%(@openssh\.com\)\?\>"
syn match sshdconfigMAC "\<umac-64@openssh\.com\>"
syn match sshdconfigMAC "\<umac-128@openssh\.com\>"
syn match sshdconfigMAC "\<hmac-sha1-etm@openssh\.com\>"
@@ -108,12 +107,9 @@ syn keyword sshdconfigSysLogFacility LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7
syn keyword sshdconfigCompression delayed
-syn match sshdconfigIPQoS "af1[123]"
-syn match sshdconfigIPQoS "af2[123]"
-syn match sshdconfigIPQoS "af3[123]"
-syn match sshdconfigIPQoS "af4[123]"
-syn match sshdconfigIPQoS "cs[0-7]"
-syn keyword sshdconfigIPQoS ef lowdelay throughput reliability
+syn match sshdconfigIPQoS "\<af[1-4][1-3]\>"
+syn match sshdconfigIPQoS "\<cs[0-7]\>"
+syn keyword sshdconfigIPQoS ef le lowdelay throughput reliability
syn keyword sshdconfigKexAlgo diffie-hellman-group1-sha1
syn keyword sshdconfigKexAlgo diffie-hellman-group14-sha1
@@ -125,20 +121,20 @@ syn keyword sshdconfigKexAlgo diffie-hellman-group-exchange-sha256
syn keyword sshdconfigKexAlgo ecdh-sha2-nistp256
syn keyword sshdconfigKexAlgo ecdh-sha2-nistp384
syn keyword sshdconfigKexAlgo ecdh-sha2-nistp521
-syn keyword sshdconfigKexAlgo curve25519-sha256
-syn match sshdconfigKexAlgo "\<curve25519-sha256@libssh\.org\>"
+syn match sshdconfigKexAlgo "\<curve25519-sha256\%(@libssh\.org\)\?\>"
syn match sshdconfigKexAlgo "\<sntrup4591761x25519-sha512@tinyssh\.org\>"
+syn match sshdconfigKexAlgo "\<sntrup761x25519-sha512@openssh\.com\>"
syn keyword sshdconfigTunnel point-to-point ethernet
syn keyword sshdconfigSubsystem internal-sftp
-syn match sshdconfigVar "%[hu]\>"
+syn match sshdconfigVar "%[CDFfhiKksTtUu]\>"
syn match sshdconfigVar "%%"
syn match sshdconfigSpecial "[*?]"
-syn match sshdconfigNumber "\d\+"
+syn match sshdconfigNumber "\<\d\+\>"
syn match sshdconfigHostPort "\<\(\d\{1,3}\.\)\{3}\d\{1,3}\(:\d\+\)\?\>"
syn match sshdconfigHostPort "\<\([-a-zA-Z0-9]\+\.\)\+[-a-zA-Z0-9]\{2,}\(:\d\+\)\?\>"
" FIXME: this matches quite a few things which are NOT valid IPv6 addresses
@@ -162,15 +158,16 @@ syn keyword sshdconfigKeyword AllowStreamLocalForwarding
syn keyword sshdconfigKeyword AllowTcpForwarding
syn keyword sshdconfigKeyword AllowUsers
syn keyword sshdconfigKeyword AuthenticationMethods
-syn keyword sshdconfigKeyword AuthorizedKeysFile
syn keyword sshdconfigKeyword AuthorizedKeysCommand
syn keyword sshdconfigKeyword AuthorizedKeysCommandUser
+syn keyword sshdconfigKeyword AuthorizedKeysFile
syn keyword sshdconfigKeyword AuthorizedPrincipalsCommand
syn keyword sshdconfigKeyword AuthorizedPrincipalsCommandUser
syn keyword sshdconfigKeyword AuthorizedPrincipalsFile
syn keyword sshdconfigKeyword Banner
syn keyword sshdconfigKeyword CASignatureAlgorithms
syn keyword sshdconfigKeyword ChallengeResponseAuthentication
+syn keyword sshdconfigKeyword ChannelTimeout
syn keyword sshdconfigKeyword ChrootDirectory
syn keyword sshdconfigKeyword Ciphers
syn keyword sshdconfigKeyword ClientAliveCountMax
@@ -187,22 +184,22 @@ syn keyword sshdconfigKeyword GatewayPorts
syn keyword sshdconfigKeyword GSSAPIAuthentication
syn keyword sshdconfigKeyword GSSAPICleanupCredentials
syn keyword sshdconfigKeyword GSSAPIEnablek5users
-syn keyword sshdconfigKeyword GSSAPIKeyExchange
syn keyword sshdconfigKeyword GSSAPIKexAlgorithms
+syn keyword sshdconfigKeyword GSSAPIKeyExchange
syn keyword sshdconfigKeyword GSSAPIStoreCredentialsOnRekey
syn keyword sshdconfigKeyword GSSAPIStrictAcceptorCheck
-syn keyword sshdconfigKeyword HostCertificate
-syn keyword sshdconfigKeyword HostKey
-syn keyword sshdconfigKeyword HostKeyAgent
-syn keyword sshdconfigKeyword HostKeyAlgorithms
syn keyword sshdconfigKeyword HostbasedAcceptedAlgorithms
syn keyword sshdconfigKeyword HostbasedAcceptedKeyTypes
syn keyword sshdconfigKeyword HostbasedAuthentication
syn keyword sshdconfigKeyword HostbasedUsesNameFromPacketOnly
-syn keyword sshdconfigKeyword IPQoS
+syn keyword sshdconfigKeyword HostCertificate
+syn keyword sshdconfigKeyword HostKey
+syn keyword sshdconfigKeyword HostKeyAgent
+syn keyword sshdconfigKeyword HostKeyAlgorithms
syn keyword sshdconfigKeyword IgnoreRhosts
syn keyword sshdconfigKeyword IgnoreUserKnownHosts
syn keyword sshdconfigKeyword Include
+syn keyword sshdconfigKeyword IPQoS
syn keyword sshdconfigKeyword KbdInteractiveAuthentication
syn keyword sshdconfigKeyword KerberosAuthentication
syn keyword sshdconfigKeyword KerberosGetAFSToken
@@ -213,9 +210,9 @@ syn keyword sshdconfigKeyword KerberosUseKuserok
syn keyword sshdconfigKeyword KexAlgorithms
syn keyword sshdconfigKeyword KeyRegenerationInterval
syn keyword sshdconfigKeyword ListenAddress
+syn keyword sshdconfigKeyword LoginGraceTime
syn keyword sshdconfigKeyword LogLevel
syn keyword sshdconfigKeyword LogVerbose
-syn keyword sshdconfigKeyword LoginGraceTime
syn keyword sshdconfigKeyword MACs
syn keyword sshdconfigKeyword Match
syn keyword sshdconfigKeyword MaxAuthTries
@@ -223,8 +220,6 @@ syn keyword sshdconfigKeyword MaxSessions
syn keyword sshdconfigKeyword MaxStartups
syn keyword sshdconfigKeyword ModuliFile
syn keyword sshdconfigKeyword PasswordAuthentication
-syn keyword sshdconfigKeyword PerSourceMaxStartups
-syn keyword sshdconfigKeyword PerSourceNetBlockSize
syn keyword sshdconfigKeyword PermitBlacklistedKeys
syn keyword sshdconfigKeyword PermitEmptyPasswords
syn keyword sshdconfigKeyword PermitListen
@@ -234,6 +229,8 @@ syn keyword sshdconfigKeyword PermitTTY
syn keyword sshdconfigKeyword PermitTunnel
syn keyword sshdconfigKeyword PermitUserEnvironment
syn keyword sshdconfigKeyword PermitUserRC
+syn keyword sshdconfigKeyword PerSourceMaxStartups
+syn keyword sshdconfigKeyword PerSourceNetBlockSize
syn keyword sshdconfigKeyword PidFile
syn keyword sshdconfigKeyword Port
syn keyword sshdconfigKeyword PrintLastLog
@@ -243,23 +240,24 @@ syn keyword sshdconfigKeyword PubkeyAcceptedAlgorithms
syn keyword sshdconfigKeyword PubkeyAcceptedKeyTypes
syn keyword sshdconfigKeyword PubkeyAuthentication
syn keyword sshdconfigKeyword PubkeyAuthOptions
-syn keyword sshdconfigKeyword RSAAuthentication
+syn keyword sshdconfigKeyword RDomain
syn keyword sshdconfigKeyword RekeyLimit
syn keyword sshdconfigKeyword RequiredRSASize
syn keyword sshdconfigKeyword RevokedKeys
-syn keyword sshdconfigKeyword RDomain
syn keyword sshdconfigKeyword RhostsRSAAuthentication
+syn keyword sshdconfigKeyword RSAAuthentication
syn keyword sshdconfigKeyword SecurityKeyProvider
syn keyword sshdconfigKeyword ServerKeyBits
syn keyword sshdconfigKeyword SetEnv
syn keyword sshdconfigKeyword ShowPatchLevel
-syn keyword sshdconfigKeyword StrictModes
syn keyword sshdconfigKeyword StreamLocalBindMask
syn keyword sshdconfigKeyword StreamLocalBindUnlink
+syn keyword sshdconfigKeyword StrictModes
syn keyword sshdconfigKeyword Subsystem
syn keyword sshdconfigKeyword SyslogFacility
syn keyword sshdconfigKeyword TCPKeepAlive
syn keyword sshdconfigKeyword TrustedUserCAKeys
+syn keyword sshdconfigKeyword UnusedConnectionTimeout
syn keyword sshdconfigKeyword UseBlacklist
syn keyword sshdconfigKeyword UseBlocklist
syn keyword sshdconfigKeyword UseDNS
@@ -278,14 +276,13 @@ syn keyword sshdconfigKeyword XAuthLocation
hi def link sshdconfigComment Comment
hi def link sshdconfigTodo Todo
hi def link sshdconfigHostPort sshdconfigConstant
-hi def link sshdconfigTime sshdconfigConstant
-hi def link sshdconfigNumber sshdconfigConstant
+hi def link sshdconfigTime Number
+hi def link sshdconfigNumber Number
hi def link sshdconfigConstant Constant
-hi def link sshdconfigYesNo sshdconfigEnum
+hi def link sshdconfigYesNo Boolean
hi def link sshdconfigAddressFamily sshdconfigEnum
hi def link sshdconfigPrivilegeSeparation sshdconfigEnum
hi def link sshdconfigTcpForwarding sshdconfigEnum
-hi def link sshdconfigRootLogin sshdconfigEnum
hi def link sshdconfigCiphers sshdconfigEnum
hi def link sshdconfigMAC sshdconfigEnum
hi def link sshdconfigHostKeyAlgo sshdconfigEnum
diff --git a/src/klib/kvec.h b/src/klib/kvec.h
index a32b35a14c..1b9e6fd9f8 100644
--- a/src/klib/kvec.h
+++ b/src/klib/kvec.h
@@ -153,6 +153,12 @@
type init_array[INIT_SIZE]; \
}
+#define KVI_INITIAL_VALUE(v) { \
+ .size = 0, \
+ .capacity = ARRAY_SIZE((v).init_array), \
+ .items = (v).init_array \
+}
+
/// Initialize vector with preallocated array
///
/// @param[out] v Vector to initialize.
@@ -218,6 +224,17 @@ static inline void *_memcpy_free(void *const restrict dest, void *const restrict
} \
} while (0)
+#define kvi_concat_len(v, data, len) \
+ if (len > 0) { \
+ kvi_ensure_more_space(v, len); \
+ assert((v).items); \
+ memcpy((v).items + (v).size, data, sizeof((v).items[0]) * len); \
+ (v).size = (v).size + len; \
+ }
+
+#define kvi_concat(v, str) kvi_concat_len(v, str, strlen(str))
+#define kvi_splice(v1, v0) kvi_concat_len(v1, (v0).items, (v0).size)
+
/// Get location where to store new element to a vector with preallocated array
///
/// @param[in,out] v Vector to push to.
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 2b3ebb7bfb..2fb8f3d554 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -167,7 +167,7 @@ Dictionary nvim_get_hl(Integer ns_id, Dict(get_highlight) *opts, Arena *arena, E
/// @param[out] err Error details, if any
///
// TODO(bfredl): val should take update vs reset flag
-void nvim_set_hl(Integer ns_id, String name, Dict(highlight) *val, Error *err)
+void nvim_set_hl(uint64_t channel_id, Integer ns_id, String name, Dict(highlight) *val, Error *err)
FUNC_API_SINCE(7)
{
int hl_id = syn_check_group(name.data, name.size);
@@ -184,7 +184,9 @@ void nvim_set_hl(Integer ns_id, String name, Dict(highlight) *val, Error *err)
HlAttrs attrs = dict2hlattrs(val, true, &link_id, err);
if (!ERROR_SET(err)) {
- ns_hl_def((NS)ns_id, hl_id, attrs, link_id, val);
+ WITH_SCRIPT_CONTEXT(channel_id, {
+ ns_hl_def((NS)ns_id, hl_id, attrs, link_id, val);
+ });
}
}
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 00cfef23c7..c2cc8bd9b8 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -1750,7 +1750,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
saveRedobuff(&save_redo);
did_save_redobuff = true;
}
- did_filetype = keep_filetype;
+ curbuf->b_did_filetype = curbuf->b_keep_filetype;
}
// Note that we are applying autocmds. Some commands need to know.
@@ -1760,7 +1760,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
// Remember that FileType was triggered. Used for did_filetype().
if (event == EVENT_FILETYPE) {
- did_filetype = true;
+ curbuf->b_did_filetype = true;
}
char *tail = path_tail(fname);
@@ -1864,7 +1864,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
if (did_save_redobuff) {
restoreRedobuff(&save_redo);
}
- did_filetype = false;
+ curbuf->b_did_filetype = false;
while (au_pending_free_buf != NULL) {
buf_T *b = au_pending_free_buf->b_next;
@@ -1901,7 +1901,7 @@ BYPASS_AU:
}
if (retval == OK && event == EVENT_FILETYPE) {
- au_did_filetype = true;
+ curbuf->b_au_did_filetype = true;
}
return retval;
@@ -2645,7 +2645,7 @@ void do_filetype_autocmd(buf_T *buf, bool force)
secure = 0;
ft_recursive++;
- did_filetype = true;
+ buf->b_did_filetype = true;
// Only pass true for "force" when it is true or
// used recursively, to avoid endless recurrence.
apply_autocmds(EVENT_FILETYPE, buf->b_p_ft, buf->b_fname, force || ft_recursive == 1, buf);
diff --git a/src/nvim/autocmd.h b/src/nvim/autocmd.h
index 8019cb7145..b298fbb6a1 100644
--- a/src/nvim/autocmd.h
+++ b/src/nvim/autocmd.h
@@ -15,14 +15,6 @@
#include "nvim/pos_defs.h"
#include "nvim/types_defs.h"
-// Set by the apply_autocmds_group function if the given event is equal to
-// EVENT_FILETYPE. Used by the readfile function in order to determine if
-// EVENT_BUFREADPOST triggered the EVENT_FILETYPE.
-//
-// Relying on this value requires one to reset it prior calling
-// apply_autocmds_group.
-EXTERN bool au_did_filetype INIT( = false);
-
/// For CursorMoved event
EXTERN win_T *last_cursormoved_win INIT( = NULL);
/// For CursorMoved event, only used when last_cursormoved_win == curwin
@@ -31,9 +23,6 @@ EXTERN pos_T last_cursormoved INIT( = { 0, 0, 0 });
EXTERN bool autocmd_busy INIT( = false); ///< Is apply_autocmds() busy?
EXTERN int autocmd_no_enter INIT( = false); ///< Buf/WinEnter autocmds disabled
EXTERN int autocmd_no_leave INIT( = false); ///< Buf/WinLeave autocmds disabled
-EXTERN bool did_filetype INIT( = false); ///< FileType event found
-/// value for did_filetype when starting to execute autocommands
-EXTERN bool keep_filetype INIT( = false);
/// When deleting the current buffer, another one must be loaded.
/// If we know which one is preferred, au_new_curbuf is set to it.
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 3c2d52e6ad..39d0d24d47 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -267,7 +267,7 @@ int open_buffer(bool read_stdin, exarg_T *eap, int flags_arg)
// The autocommands in readfile() may change the buffer, but only AFTER
// reading the file.
set_bufref(&old_curbuf, curbuf);
- modified_was_set = false;
+ curbuf->b_modified_was_set = false;
// mark cursor position as being invalid
curwin->w_valid = 0;
@@ -350,7 +350,7 @@ int open_buffer(bool read_stdin, exarg_T *eap, int flags_arg)
// the changed flag. Unless in readonly mode: "ls | nvim -R -".
// When interrupted and 'cpoptions' contains 'i' set changed flag.
if ((got_int && vim_strchr(p_cpo, CPO_INTMOD) != NULL)
- || modified_was_set // ":set modified" used in autocmd
+ || curbuf->b_modified_was_set // autocmd did ":set modified"
|| (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL)) {
changed(curbuf);
} else if (retval != FAIL && !read_stdin && !read_fifo) {
@@ -1725,7 +1725,7 @@ void enter_buffer(buf_T *buf)
// ":ball" used in an autocommand. If there already is a filetype we
// might prefer to keep it.
if (*curbuf->b_p_ft == NUL) {
- did_filetype = false;
+ curbuf->b_did_filetype = false;
}
open_buffer(false, NULL, 0);
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 7f7300706c..083508fe86 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -461,6 +461,19 @@ struct file_buffer {
bool b_marks_read; // Have we read ShaDa marks yet?
+ bool b_modified_was_set; ///< did ":set modified"
+ bool b_did_filetype; ///< FileType event found
+ bool b_keep_filetype; ///< value for did_filetype when starting
+ ///< to execute autocommands
+
+ /// Set by the apply_autocmds_group function if the given event is equal to
+ /// EVENT_FILETYPE. Used by the readfile function in order to determine if
+ /// EVENT_BUFREADPOST triggered the EVENT_FILETYPE.
+ ///
+ /// Relying on this value requires one to reset it prior calling
+ /// apply_autocmds_group().
+ bool b_au_did_filetype;
+
// The following only used in undo.c.
u_header_T *b_u_oldhead; // pointer to oldest header
u_header_T *b_u_newhead; // pointer to newest header; may not be valid
diff --git a/src/nvim/change.c b/src/nvim/change.c
index b6f2be547f..fce0de49bb 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -1838,6 +1838,13 @@ bool open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
saved_line = NULL;
if (did_append) {
+ // Always move extmarks - Here we move only the line where the cursor is,
+ // the previous mark_adjust() took care of the lines after.
+ int cols_added = mincol - 1 + less_cols_off - less_cols;
+ extmark_splice(curbuf, (int)lnum - 1, mincol - 1 - cols_spliced,
+ 0, less_cols_off, less_cols_off,
+ 1, cols_added, 1 + cols_added, kExtmarkUndo);
+
changed_lines(curbuf, curwin->w_cursor.lnum, curwin->w_cursor.col,
curwin->w_cursor.lnum + 1, 1, true);
did_append = false;
@@ -1848,12 +1855,6 @@ bool open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
curwin->w_cursor.col + less_cols_off,
1, -less_cols, 0);
}
- // Always move extmarks - Here we move only the line where the
- // cursor is, the previous mark_adjust takes care of the lines after
- int cols_added = mincol - 1 + less_cols_off - less_cols;
- extmark_splice(curbuf, (int)lnum - 1, mincol - 1 - cols_spliced,
- 0, less_cols_off, less_cols_off,
- 1, cols_added, 1 + cols_added, kExtmarkUndo);
} else {
changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
}
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 8b8345657c..0326096486 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -365,9 +365,10 @@ static void insert_enter(InsertState *s)
did_cursorhold = false;
// ins_redraw() triggers TextChangedI only when no characters
- // are in the typeahead buffer, so only reset curbuf->b_last_changedtick
+ // are in the typeahead buffer, so reset curbuf->b_last_changedtick
// if the TextChangedI was not blocked by char_avail() (e.g. using :norm!)
- if (!char_avail()) {
+ // and the TextChangedI autocommand has been triggered
+ if (!char_avail() && curbuf->b_last_changedtick_i == buf_get_changedtick(curbuf)) {
curbuf->b_last_changedtick = buf_get_changedtick(curbuf);
}
}
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 99da15ddd7..d3fe2c7e33 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -1361,7 +1361,7 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, EvalFuncData fp
/// "did_filetype()" function
static void f_did_filetype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- rettv->vval.v_number = did_filetype;
+ rettv->vval.v_number = curbuf->b_did_filetype;
}
/// "diff_filler()" function
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index dd30cdbba4..6c997b9500 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -2466,7 +2466,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// Since we are starting to edit a file, consider the filetype to be
// unset. Helps for when an autocommand changes files and expects syntax
// highlighting to work in the other file.
- did_filetype = false;
+ curbuf->b_did_filetype = false;
// other_file oldbuf
// false false re-edit same file, buffer is re-used
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index ee738d9e92..318d2e4ff2 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -7382,7 +7382,7 @@ void filetype_maybe_enable(void)
/// ":setfiletype [FALLBACK] {name}"
static void ex_setfiletype(exarg_T *eap)
{
- if (did_filetype) {
+ if (curbuf->b_did_filetype) {
return;
}
@@ -7393,7 +7393,7 @@ static void ex_setfiletype(exarg_T *eap)
set_option_value_give_err(kOptFiletype, CSTR_AS_OPTVAL(arg), OPT_LOCAL);
if (arg != eap->arg) {
- did_filetype = false;
+ curbuf->b_did_filetype = false;
}
}
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 6b50b031a3..df9c4928c9 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -234,7 +234,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
int using_b_fname;
static char *msg_is_a_directory = N_("is a directory");
- au_did_filetype = false; // reset before triggering any autocommands
+ curbuf->b_au_did_filetype = false; // reset before triggering any autocommands
curbuf->b_no_eol_lnum = 0; // in case it was set by the previous read
@@ -1854,7 +1854,7 @@ failed:
} else if (newfile || (read_buffer && sfname != NULL)) {
apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname,
false, curbuf, eap);
- if (!au_did_filetype && *curbuf->b_p_ft != NUL) {
+ if (!curbuf->b_au_did_filetype && *curbuf->b_p_ft != NUL) {
// EVENT_FILETYPE was not triggered but the buffer already has a
// filetype. Trigger EVENT_FILETYPE using the existing filetype.
apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname, true, curbuf);
@@ -3151,7 +3151,7 @@ void buf_reload(buf_T *buf, int orig_mode, bool reload_options)
if (saved == OK) {
curbuf->b_flags |= BF_CHECK_RO; // check for RO again
- keep_filetype = true; // don't detect 'filetype'
+ curbuf->b_keep_filetype = true; // don't detect 'filetype'
if (readfile(buf->b_ffname, buf->b_fname, 0, 0,
(linenr_T)MAXLNUM, &ea, flags, shortmess(SHM_FILEINFO)) != OK) {
if (!aborting()) {
@@ -3199,7 +3199,7 @@ void buf_reload(buf_T *buf, int orig_mode, bool reload_options)
curwin->w_cursor = old_cursor;
check_cursor(curwin);
update_topline(curwin);
- keep_filetype = false;
+ curbuf->b_keep_filetype = false;
// Update folds unless they are defined manually.
FOR_ALL_TAB_WINDOWS(tp, wp) {
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index f68bd7098b..665f60a49e 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -94,6 +94,12 @@ static buffheader_T readbuf1 = { { NULL, { NUL } }, NULL, 0, 0 };
/// Second read ahead buffer. Used for redo.
static buffheader_T readbuf2 = { { NULL, { NUL } }, NULL, 0, 0 };
+/// Buffer used to store typed characters for vim.on_key().
+static kvec_withinit_t(char, MAXMAPLEN) on_key_buf = KVI_INITIAL_VALUE(on_key_buf);
+
+/// Number of following bytes that should not be stored for vim.on_key().
+static size_t no_on_key_len = 0;
+
static int typeahead_char = 0; ///< typeahead char that's not flushed
/// When block_redo is true the redo buffer will not be changed.
@@ -994,14 +1000,19 @@ int ins_typebuf(char *str, int noremap, int offset, bool nottyped, bool silent)
/// Uses cmd_silent, KeyTyped and KeyNoremap to restore the flags belonging to
/// the char.
///
+/// @param no_on_key don't store these bytes for vim.on_key()
+///
/// @return the length of what was inserted
-int ins_char_typebuf(int c, int modifiers)
+int ins_char_typebuf(int c, int modifiers, bool no_on_key)
{
char buf[MB_MAXBYTES * 3 + 4];
unsigned len = special_to_buf(c, modifiers, true, buf);
assert(len < sizeof(buf));
buf[len] = NUL;
ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent);
+ if (KeyTyped && no_on_key) {
+ no_on_key_len += len;
+ }
return (int)len;
}
@@ -1102,38 +1113,82 @@ void del_typebuf(int len, int offset)
}
/// Write typed characters to script file.
-/// If recording is on put the character in the recordbuffer.
+/// If recording is on put the character in the record buffer.
static void gotchars(const uint8_t *chars, size_t len)
FUNC_ATTR_NONNULL_ALL
{
const uint8_t *s = chars;
- static uint8_t buf[4] = { 0 };
+ int c = NUL;
+ static int prev_c = NUL;
+ static uint8_t buf[MB_MAXBYTES * 3 + 4] = { 0 };
static size_t buflen = 0;
+ static unsigned pending = 0;
+ static bool in_special = false;
+ static bool in_mbyte = false;
size_t todo = len;
- while (todo--) {
- buf[buflen++] = *s++;
+ for (; todo--; prev_c = c) {
+ c = buf[buflen++] = *s++;
+ if (pending > 0) {
+ pending--;
+ }
// When receiving a special key sequence, store it until we have all
// the bytes and we can decide what to do with it.
- if (buflen == 1 && buf[0] == K_SPECIAL) {
- continue;
+ if ((pending == 0 || in_mbyte) && c == K_SPECIAL) {
+ pending += 2;
+ if (!in_mbyte) {
+ in_special = true;
+ }
}
- if (buflen == 2) {
+
+ if (pending > 0) {
continue;
}
+ if (!in_mbyte) {
+ if (in_special) {
+ in_special = false;
+ if (prev_c == KS_MODIFIER) {
+ // When receiving a modifier, wait for the modified key.
+ continue;
+ }
+ c = TO_SPECIAL(prev_c, c);
+ }
+ // When receiving a multibyte character, store it until we have all
+ // the bytes, so that it won't be split between two buffer blocks,
+ // and delete_buff_tail() will work properly.
+ pending = MB_BYTE2LEN_CHECK(c) - 1;
+ if (pending > 0) {
+ in_mbyte = true;
+ continue;
+ }
+ } else {
+ // Stored all bytes of a multibyte character.
+ in_mbyte = false;
+ }
+
// Handle one byte at a time; no translation to be done.
for (size_t i = 0; i < buflen; i++) {
updatescript(buf[i]);
}
+ buf[buflen] = NUL;
+
if (reg_recording != 0) {
- buf[buflen] = NUL;
add_buff(&recordbuff, (char *)buf, (ptrdiff_t)buflen);
// remember how many chars were last recorded
last_recorded_len += buflen;
}
+
+ if (buflen > no_on_key_len) {
+ vim_unescape_ks((char *)buf + no_on_key_len);
+ kvi_concat(on_key_buf, (char *)buf + no_on_key_len);
+ no_on_key_len = 0;
+ } else {
+ no_on_key_len -= buflen;
+ }
+
buflen = 0;
}
@@ -1151,6 +1206,7 @@ static void gotchars(const uint8_t *chars, size_t len)
void gotchars_ignore(void)
{
uint8_t nop_buf[3] = { K_SPECIAL, KS_EXTRA, KE_IGNORE };
+ no_on_key_len += 3;
gotchars(nop_buf, 3);
}
@@ -1621,9 +1677,13 @@ int vgetc(void)
if (!no_mapping && KeyTyped && mod_mask == MOD_MASK_ALT && !(State & MODE_TERMINAL)
&& !is_mouse_key(c)) {
mod_mask = 0;
- int len = ins_char_typebuf(c, 0);
- ins_char_typebuf(ESC, 0);
- ungetchars(len + 3); // K_SPECIAL KS_MODIFIER MOD_MASK_ALT takes 3 more bytes
+ int len = ins_char_typebuf(c, 0, false);
+ ins_char_typebuf(ESC, 0, false);
+ int old_len = len + 3; // K_SPECIAL KS_MODIFIER MOD_MASK_ALT takes 3 more bytes
+ ungetchars(old_len);
+ if (on_key_buf.size >= (size_t)old_len) {
+ on_key_buf.size -= (size_t)old_len;
+ }
continue;
}
@@ -1639,7 +1699,9 @@ int vgetc(void)
may_garbage_collect = false;
// Execute Lua on_key callbacks.
- nlua_execute_on_key(c);
+ nlua_execute_on_key(c, on_key_buf.items, on_key_buf.size);
+ kvi_destroy(on_key_buf);
+ kvi_init(on_key_buf);
// Need to process the character before we know it's safe to do something
// else.
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index bb9aca38b7..83fef1fe75 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -341,8 +341,6 @@ EXTERN bool did_check_timestamps INIT( = false); // did check timestamps
// recently
EXTERN int no_check_timestamps INIT( = 0); // Don't check timestamps
-EXTERN int modified_was_set; // did ":set modified"
-
// Mouse coordinates, set by handle_mouse_event()
EXTERN int mouse_grid;
EXTERN int mouse_row;
diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c
index f4800deb90..05b6dfb896 100644
--- a/src/nvim/highlight_group.c
+++ b/src/nvim/highlight_group.c
@@ -889,11 +889,13 @@ void set_hl_group(int id, HlAttrs attrs, Dict(highlight) *dict, int link_id)
g->sg_link = link_id;
g->sg_script_ctx = current_sctx;
g->sg_script_ctx.sc_lnum += SOURCING_LNUM;
+ nlua_set_sctx(&g->sg_script_ctx);
g->sg_set |= SG_LINK;
if (is_default) {
g->sg_deflink = link_id;
g->sg_deflink_sctx = current_sctx;
g->sg_deflink_sctx.sc_lnum += SOURCING_LNUM;
+ nlua_set_sctx(&g->sg_deflink_sctx);
}
} else {
g->sg_link = 0;
@@ -934,6 +936,7 @@ void set_hl_group(int id, HlAttrs attrs, Dict(highlight) *dict, int link_id)
g->sg_script_ctx = current_sctx;
g->sg_script_ctx.sc_lnum += SOURCING_LNUM;
+ nlua_set_sctx(&g->sg_script_ctx);
g->sg_attr = hl_get_syn_attr(0, id, attrs);
@@ -1914,7 +1917,7 @@ static void set_hl_attr(int idx)
at_en.cterm_bg_color = (int16_t)sgp->sg_cterm_bg;
at_en.rgb_ae_attr = (int16_t)sgp->sg_gui;
// FIXME(tarruda): The "unset value" for rgb is -1, but since hlgroup is
- // initialized with 0(by garray functions), check for sg_rgb_{f,b}g_name
+ // initialized with 0 (by garray functions), check for sg_rgb_{f,b}g_name
// before setting attr_entry->{f,g}g_color to a other than -1
at_en.rgb_fg_color = sgp->sg_rgb_fg_idx != kColorIdxNone ? sgp->sg_rgb_fg : -1;
at_en.rgb_bg_color = sgp->sg_rgb_bg_idx != kColorIdxNone ? sgp->sg_rgb_bg : -1;
@@ -2472,7 +2475,7 @@ color_name_table_T color_name_table[] = {
{ "Cyan4", RGB_(0x0, 0x8b, 0x8b) },
{ "DarkBlue", RGB_(0x00, 0x00, 0x8b) },
{ "DarkCyan", RGB_(0x00, 0x8b, 0x8b) },
- { "DarkGoldenRod", RGB_(0xb8, 0x86, 0x0b) },
+ { "DarkGoldenrod", RGB_(0xb8, 0x86, 0x0b) },
{ "DarkGoldenrod1", RGB_(0xff, 0xb9, 0xf) },
{ "DarkGoldenrod2", RGB_(0xee, 0xad, 0xe) },
{ "DarkGoldenrod3", RGB_(0xcd, 0x95, 0xc) },
@@ -2546,7 +2549,7 @@ color_name_table_T color_name_table[] = {
{ "Gold2", RGB_(0xee, 0xc9, 0x0) },
{ "Gold3", RGB_(0xcd, 0xad, 0x0) },
{ "Gold4", RGB_(0x8b, 0x75, 0x0) },
- { "GoldenRod", RGB_(0xda, 0xa5, 0x20) },
+ { "Goldenrod", RGB_(0xda, 0xa5, 0x20) },
{ "Goldenrod1", RGB_(0xff, 0xc1, 0x25) },
{ "Goldenrod2", RGB_(0xee, 0xb4, 0x22) },
{ "Goldenrod3", RGB_(0xcd, 0x9b, 0x1d) },
@@ -2815,7 +2818,7 @@ color_name_table_T color_name_table[] = {
{ "LightGoldenrod2", RGB_(0xee, 0xdc, 0x82) },
{ "LightGoldenrod3", RGB_(0xcd, 0xbe, 0x70) },
{ "LightGoldenrod4", RGB_(0x8b, 0x81, 0x4c) },
- { "LightGoldenRodYellow", RGB_(0xfa, 0xfa, 0xd2) },
+ { "LightGoldenrodYellow", RGB_(0xfa, 0xfa, 0xd2) },
{ "LightGray", RGB_(0xd3, 0xd3, 0xd3) },
{ "LightGreen", RGB_(0x90, 0xee, 0x90) },
{ "LightGrey", RGB_(0xd3, 0xd3, 0xd3) },
@@ -2900,6 +2903,10 @@ color_name_table_T color_name_table[] = {
// for foreground in light/dark color scheme.
{ "NvimDarkBlue", RGB_(0x00, 0x4c, 0x73) },
{ "NvimDarkCyan", RGB_(0x00, 0x73, 0x73) },
+ { "NvimDarkGray1", RGB_(0x07, 0x08, 0x0d) },
+ { "NvimDarkGray2", RGB_(0x14, 0x16, 0x1b) },
+ { "NvimDarkGray3", RGB_(0x2c, 0x2e, 0x33) },
+ { "NvimDarkGray4", RGB_(0x4f, 0x52, 0x58) },
{ "NvimDarkGreen", RGB_(0x00, 0x55, 0x23) },
{ "NvimDarkGrey1", RGB_(0x07, 0x08, 0x0d) },
{ "NvimDarkGrey2", RGB_(0x14, 0x16, 0x1b) },
@@ -2910,6 +2917,10 @@ color_name_table_T color_name_table[] = {
{ "NvimDarkYellow", RGB_(0x6b, 0x53, 0x00) },
{ "NvimLightBlue", RGB_(0xa6, 0xdb, 0xff) },
{ "NvimLightCyan", RGB_(0x8c, 0xf8, 0xf7) },
+ { "NvimLightGray1", RGB_(0xee, 0xf1, 0xf8) },
+ { "NvimLightGray2", RGB_(0xe0, 0xe2, 0xea) },
+ { "NvimLightGray3", RGB_(0xc4, 0xc6, 0xcd) },
+ { "NvimLightGray4", RGB_(0x9b, 0x9e, 0xa4) },
{ "NvimLightGreen", RGB_(0xb3, 0xf6, 0xc0) },
{ "NvimLightGrey1", RGB_(0xee, 0xf1, 0xf8) },
{ "NvimLightGrey2", RGB_(0xe0, 0xe2, 0xea) },
@@ -2940,7 +2951,7 @@ color_name_table_T color_name_table[] = {
{ "Orchid2", RGB_(0xee, 0x7a, 0xe9) },
{ "Orchid3", RGB_(0xcd, 0x69, 0xc9) },
{ "Orchid4", RGB_(0x8b, 0x47, 0x89) },
- { "PaleGoldenRod", RGB_(0xee, 0xe8, 0xaa) },
+ { "PaleGoldenrod", RGB_(0xee, 0xe8, 0xaa) },
{ "PaleGreen", RGB_(0x98, 0xfb, 0x98) },
{ "PaleGreen1", RGB_(0x9a, 0xff, 0x9a) },
{ "PaleGreen2", RGB_(0x90, 0xee, 0x90) },
diff --git a/src/nvim/highlight_group.h b/src/nvim/highlight_group.h
index 47d58d20f2..edf5fbde16 100644
--- a/src/nvim/highlight_group.h
+++ b/src/nvim/highlight_group.h
@@ -12,7 +12,7 @@ typedef struct {
char *name;
RgbValue color;
} color_name_table_T;
-extern color_name_table_T color_name_table[700];
+extern color_name_table_T color_name_table[708];
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "highlight_group.h.generated.h"
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index d5d35c5295..cfc68dc08f 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -2064,9 +2064,9 @@ char *nlua_register_table_as_callable(const typval_T *const arg)
return name;
}
-void nlua_execute_on_key(int c)
+void nlua_execute_on_key(int c, char *typed_buf, size_t typed_len)
{
- char buf[NUMBUFLEN];
+ char buf[MB_MAXBYTES * 3 + 4];
size_t buf_len = special_to_buf(c, mod_mask, false, buf);
lua_State *const lstate = global_lstate;
@@ -2085,9 +2085,12 @@ void nlua_execute_on_key(int c)
// [ vim, vim._on_key, buf ]
lua_pushlstring(lstate, buf, buf_len);
+ // [ vim, vim._on_key, buf, typed_buf ]
+ lua_pushlstring(lstate, typed_buf, typed_len);
+
int save_got_int = got_int;
got_int = false; // avoid interrupts when the key typed is Ctrl-C
- if (nlua_pcall(lstate, 1, 0)) {
+ if (nlua_pcall(lstate, 2, 0)) {
nlua_error(lstate,
_("Error executing vim.on_key Lua callback: %.*s"));
}
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 5a47908eb6..68a8b8e88b 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -1265,7 +1265,7 @@ void wait_return(int redraw)
} else if (vim_strchr("\r\n ", c) == NULL && c != Ctrl_C) {
// Put the character back in the typeahead buffer. Don't use the
// stuff buffer, because lmaps wouldn't work.
- ins_char_typebuf(vgetc_char, vgetc_mod_mask);
+ ins_char_typebuf(vgetc_char, vgetc_mod_mask, true);
do_redraw = true; // need a redraw even though there is
// typeahead
}
@@ -3431,7 +3431,7 @@ int do_dialog(int type, const char *title, const char *message, const char *butt
}
if (c == ':' && ex_cmd) {
retval = dfltbutton;
- ins_char_typebuf(':', 0);
+ ins_char_typebuf(':', 0, false);
break;
}
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index bbba8069c7..c7eb5c5793 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -1078,7 +1078,7 @@ static int normal_execute(VimState *state, int key)
// When "restart_edit" is set fake a "d"elete command, Insert mode will restart automatically.
// Insert the typed character in the typeahead buffer, so that it can
// be mapped in Insert mode. Required for ":lmap" to work.
- int len = ins_char_typebuf(vgetc_char, vgetc_mod_mask);
+ int len = ins_char_typebuf(vgetc_char, vgetc_mod_mask, true);
// When recording and gotchars() was called the character will be
// recorded again, remove the previous recording.
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 2c7922908c..799513e018 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -2244,7 +2244,7 @@ static const char *did_set_modified(optset_T *args)
save_file_ff(buf); // Buffer is unchanged
}
redraw_titles();
- modified_was_set = (int)args->os_newval.boolean;
+ buf->b_modified_was_set = (int)args->os_newval.boolean;
return NULL;
}
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index e7acf6f6ef..1d81b570b7 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -7663,8 +7663,7 @@ return {
highlighted with |hl-NonText|.
You may also want to add "lastline" to the 'display' option to show as
much of the last line as possible.
- NOTE: only partly implemented, currently works with CTRL-E, CTRL-Y,
- CTRL-D, CTRL-U, CTRL-F, CTRL-B and scrolling with the mouse.
+ NOTE: partly implemented, doesn't work yet for |gj| and |gk|.
]=],
full_name = 'smoothscroll',
pv_name = 'p_sms',
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index baa99fca65..5218e50df6 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -255,9 +255,9 @@ size_t input_enqueue(String keys)
while (rbuffer_space(input_buffer) >= 19 && ptr < end) {
// A "<x>" form occupies at least 1 characters, and produces up
// to 19 characters (1 + 5 * 3 for the char and 3 for a modifier).
- // In the case of K_SPECIAL(0x80), 3 bytes are escaped and needed,
+ // In the case of K_SPECIAL (0x80), 3 bytes are escaped and needed,
// but since the keys are UTF-8, so the first byte cannot be
- // K_SPECIAL(0x80).
+ // K_SPECIAL (0x80).
uint8_t buf[19] = { 0 };
// Do not simplify the keys here. Simplification will be done later.
unsigned new_size
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 9f431556e8..94e176bd94 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -4274,10 +4274,10 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int q
set_option_value_give_err(kOptFiletype, STATIC_CSTR_AS_OPTVAL("qf"), OPT_LOCAL);
curbuf->b_p_ma = false;
- keep_filetype = true; // don't detect 'filetype'
+ curbuf->b_keep_filetype = true; // don't detect 'filetype'
apply_autocmds(EVENT_BUFREADPOST, "quickfix", NULL, false, curbuf);
apply_autocmds(EVENT_BUFWINENTER, "quickfix", NULL, false, curbuf);
- keep_filetype = false;
+ curbuf->b_keep_filetype = false;
curbuf->b_ro_locked--;
// make sure it will be redrawn
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index 76188499e3..bc9ace0fa8 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -2392,7 +2392,7 @@ char *get_scriptname(LastSet last_set, bool *should_free)
case SID_WINLAYOUT:
return _("changed window size");
case SID_LUA:
- return _("Lua");
+ return _("Lua (run Nvim with -V1 for more details)");
case SID_API_CLIENT:
snprintf(IObuff, IOSIZE, _("API client (channel id %" PRIu64 ")"), last_set.channel_id);
return IObuff;
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 3734d55a5b..2b05a8047e 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -1631,7 +1631,10 @@ end:
return false;
}
- ins_char_typebuf(vgetc_char, vgetc_mod_mask);
+ int len = ins_char_typebuf(vgetc_char, vgetc_mod_mask, true);
+ if (KeyTyped) {
+ ungetchars(len);
+ }
return true;
}
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index d98308ee87..dc36926641 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -1593,14 +1593,12 @@ describe('API', function()
api.nvim_set_option_value('equalalways', false, {})
local status, rv = pcall(command_output, 'verbose set equalalways?')
eq(true, status)
- ok(
- nil ~= string.find(rv, 'noequalalways\n' .. '\tLast set from API client %(channel id %d+%)')
- )
+ matches('noequalalways\n' .. '\tLast set from API client %(channel id %d+%)', rv)
api.nvim_exec_lua('vim.api.nvim_set_option_value("equalalways", true, {})', {})
status, rv = pcall(command_output, 'verbose set equalalways?')
eq(true, status)
- eq(' equalalways\n\tLast set from Lua', rv)
+ eq(' equalalways\n\tLast set from Lua (run Nvim with -V1 for more details)', rv)
end)
it('updates whether the option has ever been set #25025', function()
@@ -2723,7 +2721,7 @@ describe('API', function()
it('can throw exceptions', function()
local status, err = pcall(api.nvim_get_option_value, 'invalid-option', {})
eq(false, status)
- ok(err:match("Unknown option 'invalid%-option'") ~= nil)
+ matches("Unknown option 'invalid%-option'", err)
end)
it('does not truncate error message <1 MB #5984', function()
@@ -2736,10 +2734,7 @@ describe('API', function()
it('does not leak memory on incorrect argument types', function()
local status, err = pcall(api.nvim_set_current_dir, { 'not', 'a', 'dir' })
eq(false, status)
- ok(
- err:match(': Wrong type for argument 1 when calling nvim_set_current_dir, expecting String')
- ~= nil
- )
+ matches(': Wrong type for argument 1 when calling nvim_set_current_dir, expecting String', err)
end)
describe('nvim_parse_expression', function()
@@ -3670,7 +3665,7 @@ describe('API', function()
api.nvim_buf_set_name(buf, 'mybuf')
local mark = api.nvim_get_mark('F', {})
-- Compare the path tail only
- assert(string.find(mark[4], 'mybuf$'))
+ matches('mybuf$', mark[4])
eq({ 2, 2, buf, mark[4] }, mark)
end)
it('validation', function()
diff --git a/test/functional/autocmd/textchanged_spec.lua b/test/functional/autocmd/textchanged_spec.lua
index d501560dc1..8d8058da70 100644
--- a/test/functional/autocmd/textchanged_spec.lua
+++ b/test/functional/autocmd/textchanged_spec.lua
@@ -155,10 +155,9 @@ it('TextChangedI and TextChanged', function()
feed('yypi<esc>')
eq('', eval('g:autocmd_i'))
- -- TextChanged should only trigger if change was done in Normal mode
command([[let g:autocmd_n = '']])
feed('ibar<esc>')
- eq('', eval('g:autocmd_n'))
+ eq('N8', eval('g:autocmd_n'))
local function validate_mixed_textchangedi(keys)
feed('ifoo<esc>')
@@ -191,3 +190,26 @@ it('TextChanged is triggered after :norm that enters Insert mode', function()
feed(':norm! ia<CR>')
eq(1, eval('g:a'))
end)
+
+-- oldtest: Test_Changed_ChangedI_2()
+it('TextChanged is triggered after mapping that enters & exits Insert mode', function()
+ exec([[
+ let [g:autocmd_i, g:autocmd_n] = ['','']
+
+ func! TextChangedAutocmdI(char)
+ let g:autocmd_{tolower(a:char)} = a:char .. b:changedtick
+ endfunc
+
+ augroup Test_TextChanged
+ au!
+ au TextChanged <buffer> :call TextChangedAutocmdI('N')
+ au TextChangedI <buffer> :call TextChangedAutocmdI('I')
+ augroup END
+
+ nnoremap <CR> o<Esc>
+ ]])
+
+ feed('<CR>')
+ eq('N3', eval('g:autocmd_n'))
+ eq('', eval('g:autocmd_i'))
+end)
diff --git a/test/functional/core/channels_spec.lua b/test/functional/core/channels_spec.lua
index 56a2f5a571..0ab885e02f 100644
--- a/test/functional/core/channels_spec.lua
+++ b/test/functional/core/channels_spec.lua
@@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local clear, eq, eval, next_msg, ok, source =
helpers.clear, helpers.eq, helpers.eval, helpers.next_msg, helpers.ok, helpers.source
local command, fn, api = helpers.command, helpers.fn, helpers.api
+local matches = helpers.matches
local sleep = vim.uv.sleep
local spawn, nvim_argv = helpers.spawn, helpers.nvim_argv
local get_session, set_session = helpers.get_session, helpers.set_session
@@ -277,7 +278,7 @@ describe('channels', function()
local _, err =
pcall(command, "call rpcrequest(id, 'nvim_command', 'call chanclose(v:stderr, \"stdin\")')")
- ok(string.find(err, 'E906: invalid stream for channel') ~= nil)
+ matches('E906: invalid stream for channel', err)
eq(1, eval("rpcrequest(id, 'nvim_eval', 'chanclose(v:stderr, \"stderr\")')"))
eq({ 'notification', 'stderr', { 3, { '' } } }, next_msg())
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index 9e7f1faa47..f0e61fbcc1 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -73,7 +73,7 @@ describe('jobs', function()
command("let j = jobstart('env', g:job_opts)")
end
end)
- ok(string.find(err, 'E475: Invalid argument: env') ~= nil)
+ matches('E475: Invalid argument: env', err)
end)
it('append environment #env', function()
@@ -227,7 +227,7 @@ describe('jobs', function()
command("let j = jobstart('pwd', g:job_opts)")
end
end)
- ok(string.find(err, 'E475: Invalid argument: expected valid directory$') ~= nil)
+ matches('E475: Invalid argument: expected valid directory$', err)
end)
it('error on non-executable `cwd`', function()
@@ -980,10 +980,7 @@ describe('jobs', function()
command('let g:job_opts.pty = v:true')
command('let g:job_opts.rpc = v:true')
local _, err = pcall(command, "let j = jobstart(['cat', '-'], g:job_opts)")
- ok(
- string.find(err, "E475: Invalid argument: job cannot have both 'pty' and 'rpc' options set")
- ~= nil
- )
+ matches("E475: Invalid argument: job cannot have both 'pty' and 'rpc' options set", err)
end)
it('does not crash when repeatedly failing to start shell', function()
@@ -1239,6 +1236,7 @@ describe('pty process teardown', function()
end)
it('does not prevent/delay exit. #4798 #4900', function()
+ skip(fn.executable('sleep') == 0, 'missing "sleep" command')
-- Use a nested nvim (in :term) to test without --headless.
fn.termopen({
helpers.nvim_prog,
diff --git a/test/functional/editor/meta_key_spec.lua b/test/functional/editor/meta_key_spec.lua
index b57f5c3c35..e2bdf6ba96 100644
--- a/test/functional/editor/meta_key_spec.lua
+++ b/test/functional/editor/meta_key_spec.lua
@@ -141,4 +141,29 @@ describe('meta-keys #8226 #13042', function()
// This is some text: bar
// This is some text: baz]])
end)
+
+ it('ALT/META with vim.on_key()', function()
+ feed('ifoo<CR>bar<CR>baz<Esc>gg0')
+
+ exec_lua [[
+ keys = {}
+ typed = {}
+
+ vim.on_key(function(buf, typed_buf)
+ table.insert(keys, vim.fn.keytrans(buf))
+ table.insert(typed, vim.fn.keytrans(typed_buf))
+ end)
+ ]]
+
+ -- <M-"> is reinterpreted as <Esc>"
+ feed('qrviw"ayc$FOO.<M-">apq')
+ expect([[
+ FOO.foo
+ bar
+ baz]])
+
+ -- vim.on_key() callback should only receive <Esc>"
+ eq('qrviw"ayc$FOO.<Esc>"apq', exec_lua [[return table.concat(keys, '')]])
+ eq('qrviw"ayc$FOO.<Esc>"apq', exec_lua [[return table.concat(typed, '')]])
+ end)
end)
diff --git a/test/functional/ex_cmds/arg_spec.lua b/test/functional/ex_cmds/arg_spec.lua
index 810b001ec0..45b2f50af1 100644
--- a/test/functional/ex_cmds/arg_spec.lua
+++ b/test/functional/ex_cmds/arg_spec.lua
@@ -1,6 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local eq, command, fn = helpers.eq, helpers.command, helpers.fn
local ok = helpers.ok
+local matches = helpers.matches
local clear = helpers.clear
describe(':argument', function()
@@ -15,7 +16,7 @@ describe(':argument', function()
helpers.feed([[<C-\><C-N>]])
local bufname_before = fn.bufname('%')
local bufnr_before = fn.bufnr('%')
- helpers.ok(nil ~= string.find(bufname_before, '^term://')) -- sanity
+ matches('^term://', bufname_before) -- sanity
command('argument 1')
helpers.feed([[<C-\><C-N>]])
diff --git a/test/functional/ex_cmds/edit_spec.lua b/test/functional/ex_cmds/edit_spec.lua
index b927fa418a..9d4effd72e 100644
--- a/test/functional/ex_cmds/edit_spec.lua
+++ b/test/functional/ex_cmds/edit_spec.lua
@@ -1,6 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local eq, command, fn = helpers.eq, helpers.command, helpers.fn
local ok = helpers.ok
+local matches = helpers.matches
local clear = helpers.clear
local feed = helpers.feed
@@ -14,7 +15,7 @@ describe(':edit', function()
feed([[<C-\><C-N>]])
local bufname_before = fn.bufname('%')
local bufnr_before = fn.bufnr('%')
- helpers.ok(nil ~= string.find(bufname_before, '^term://')) -- sanity
+ matches('^term://', bufname_before) -- sanity
command('edit')
diff --git a/test/functional/ex_cmds/verbose_spec.lua b/test/functional/ex_cmds/verbose_spec.lua
index 7ceb2460d3..ba90793a37 100644
--- a/test/functional/ex_cmds/verbose_spec.lua
+++ b/test/functional/ex_cmds/verbose_spec.lua
@@ -32,21 +32,30 @@ vim.api.nvim_exec2("augroup test_group\
augroup END\
", {})
+vim.api.nvim_create_autocmd('FileType', {
+ group = 'test_group',
+ pattern = 'cpp',
+ command = 'setl cindent',
+})
+
+vim.api.nvim_exec2(':highlight TestHL1 guibg=Blue', {})
+vim.api.nvim_set_hl(0, 'TestHL2', { bg = 'Green' })
+
vim.api.nvim_command("command Bdelete :bd")
vim.api.nvim_create_user_command("TestCommand", ":echo 'Hello'", {})
-vim.api.nvim_exec ("\
+vim.api.nvim_exec2 ("\
function Close_Window() abort\
wincmd -\
endfunction\
-", false)
+", {})
-local ret = vim.api.nvim_exec ("\
+local ret = vim.api.nvim_exec2 ("\
function! s:return80()\
return 80\
endfunction\
let &tw = s:return80()\
-", true)
+", {})
]]
)
exec(cmd .. ' ' .. script_file)
@@ -109,7 +118,7 @@ n \key1 * :echo "test"<CR>
)
end)
- it('"Last set" for mapping set by vim.keymap', function()
+ it('"Last set" for mapping set by vim.keymap.set', function()
local result = exec_capture(':verbose map <leader>key2')
eq(
string.format(
@@ -123,7 +132,7 @@ n \key2 * :echo "test"<CR>
)
end)
- it('"Last set" for autocmd by vim.api.nvim_exec', function()
+ it('"Last set" for autocmd set by nvim_exec2', function()
local result = exec_capture(':verbose autocmd test_group Filetype c')
eq(
string.format(
@@ -138,6 +147,47 @@ test_group FileType
)
end)
+ it('"Last set" for autocmd set by nvim_create_autocmd', function()
+ local result = exec_capture(':verbose autocmd test_group Filetype cpp')
+ eq(
+ string.format(
+ [[
+--- Autocommands ---
+test_group FileType
+ cpp setl cindent
+ Last set from %s line 13]],
+ script_location
+ ),
+ result
+ )
+ end)
+
+ it('"Last set" for highlight group set by nvim_exec2', function()
+ local result = exec_capture(':verbose highlight TestHL1')
+ eq(
+ string.format(
+ [[
+TestHL1 xxx guibg=Blue
+ Last set from %s line 19]],
+ script_location
+ ),
+ result
+ )
+ end)
+
+ it('"Last set" for highlight group set by nvim_set_hl', function()
+ local result = exec_capture(':verbose highlight TestHL2')
+ eq(
+ string.format(
+ [[
+TestHL2 xxx guibg=Green
+ Last set from %s line 20]],
+ script_location
+ ),
+ result
+ )
+ end)
+
it('"Last set" for command defined by nvim_command', function()
if cmd == 'luafile' then
pending('nvim_command does not set the script context')
@@ -148,7 +198,7 @@ test_group FileType
[[
Name Args Address Complete Definition
Bdelete 0 :bd
- Last set from %s line 13]],
+ Last set from %s line 22]],
script_location
),
result
@@ -162,7 +212,7 @@ test_group FileType
[[
Name Args Address Complete Definition
TestCommand 0 :echo 'Hello'
- Last set from %s line 14]],
+ Last set from %s line 23]],
script_location
),
result
@@ -175,7 +225,7 @@ test_group FileType
string.format(
[[
function Close_Window() abort
- Last set from %s line 16
+ Last set from %s line 25
1 wincmd -
endfunction]],
script_location
@@ -190,7 +240,7 @@ test_group FileType
string.format(
[[
textwidth=80
- Last set from %s line 22]],
+ Last set from %s line 31]],
script_location
),
result
@@ -230,7 +280,7 @@ describe('lua verbose:', function()
eq(
[[
nohlsearch
- Last set from Lua]],
+ Last set from Lua (run Nvim with -V1 for more details)]],
result
)
end)
diff --git a/test/functional/legacy/normal_spec.lua b/test/functional/legacy/normal_spec.lua
index 8b7acccc2c..3dac1da14a 100644
--- a/test/functional/legacy/normal_spec.lua
+++ b/test/functional/legacy/normal_spec.lua
@@ -2,22 +2,28 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local exec = helpers.exec
-
-before_each(clear)
+local feed = helpers.feed
+local api = helpers.api
+local eq = helpers.eq
+local fn = helpers.fn
describe('normal', function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(40, 19)
+ screen:attach()
+ end)
+
-- oldtest: Test_normal_j_below_botline()
- it(
- [["j" does not skip lines when scrolling below botline and 'foldmethod' is not "manual"]],
- function()
- local screen = Screen.new(40, 19)
- screen:attach()
- exec([[
+ it([[no skipped lines with "j" scrolling below botline and 'foldmethod' not "manual"]], function()
+ exec([[
set number foldmethod=diff scrolloff=0
call setline(1, map(range(1, 9), 'repeat(v:val, 200)'))
norm Lj
]])
- screen:expect([[
+ screen:expect([[
{8: 2 }222222222222222222222222222222222222|
{8: }222222222222222222222222222222222222|*4
{8: }22222222222222222222 |
@@ -29,6 +35,71 @@ describe('normal', function()
{8: }44444444444444444444 |
|
]])
- end
- )
+ end)
+
+ -- oldtest: Test_single_line_scroll()
+ it('(Half)-page scroll up or down reveals virtual lines #19605, #27967', function()
+ fn.setline(1, 'foobar one two three')
+ exec('set smoothscroll')
+ local ns = api.nvim_create_namespace('')
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {
+ virt_lines = { { { '---', 'IncSearch' } } },
+ virt_lines_above = true,
+ })
+ -- Nvim: not actually necessary to scroll down to hide the virtual line.
+ -- Check topfill instead of skipcol and show the screen state.
+ feed('<C-E>')
+ eq(0, fn.winsaveview().topfill)
+ local s1 = [[
+ ^foobar one two three |
+ {1:~ }|*17
+ |
+ ]]
+ screen:expect(s1)
+ feed('<C-B>')
+ eq(1, fn.winsaveview().topfill)
+ local s2 = [[
+ {2:---} |
+ ^foobar one two three |
+ {1:~ }|*16
+ |
+ ]]
+ screen:expect(s2)
+ feed('<C-E>')
+ eq(0, fn.winsaveview().topfill)
+ screen:expect(s1)
+ feed('<C-U>')
+ eq(1, fn.winsaveview().topfill)
+ screen:expect(s2)
+
+ -- Nvim: also test virt_lines below the last line
+ feed('yy100pG<C-L>')
+ api.nvim_buf_set_extmark(0, ns, 100, 0, { virt_lines = { { { '---', 'IncSearch' } } } })
+ screen:expect({
+ grid = [[
+ foobar one two three |*17
+ ^foobar one two three |
+ |
+ ]],
+ })
+ feed('<C-F>')
+ screen:expect({
+ grid = [[
+ ^foobar one two three |
+ {2:---} |
+ {1:~ }|*16
+ |
+ ]],
+ })
+ feed('ggG<C-D>')
+ screen:expect({
+ grid = [[
+ foobar one two three |*8
+ ^foobar one two three |
+ {2:---} |
+ {1:~ }|*8
+ |
+ ]],
+ })
+ end)
end)
diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua
index 2479a433e6..01dc8c2f02 100644
--- a/test/functional/lua/buffer_updates_spec.lua
+++ b/test/functional/lua/buffer_updates_spec.lua
@@ -1,5 +1,6 @@
-- Test suite for testing interactions with API bindings
local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
local command = helpers.command
local api = helpers.api
@@ -323,20 +324,60 @@ describe('lua buffer event callbacks: on_lines', function()
eq({ 'lines', 1, 6, 0, 3, 3, 9 }, api.nvim_get_var('linesev'))
end)
- it(
- 'calling nvim_buf_call() from callback does not cause Normal mode CTRL-A to misbehave #16729',
- function()
- exec_lua([[
+ it('nvim_buf_call() from callback does not cause wrong Normal mode CTRL-A #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', api.nvim_get_current_line())
- end
- )
+ feed('itest123<Esc><C-A>')
+ eq('test124', api.nvim_get_current_line())
+ end)
+
+ it('setting extmark in on_lines callback works', function()
+ local screen = Screen.new(40, 6)
+ screen:attach()
+
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'aaa', 'bbb', 'ccc' })
+ exec_lua([[
+ local ns = vim.api.nvim_create_namespace('')
+ vim.api.nvim_buf_attach(0, false, {
+ on_lines = function(_, _, _, row, _, end_row)
+ vim.api.nvim_buf_clear_namespace(0, ns, row, end_row)
+ for i = row, end_row - 1 do
+ local id = vim.api.nvim_buf_set_extmark(0, ns, i, 0, {
+ virt_text = {{ 'NEW' .. tostring(i), 'WarningMsg' }},
+ })
+ end
+ end,
+ })
+ ]])
+
+ feed('o')
+ screen:expect({
+ grid = [[
+ aaa |
+ ^ {19:NEW1} |
+ bbb |
+ ccc |
+ {1:~ }|
+ {5:-- INSERT --} |
+ ]],
+ })
+ feed('<CR>')
+ screen:expect({
+ grid = [[
+ aaa |
+ {19:NEW1} |
+ ^ {19:NEW2} |
+ bbb |
+ ccc |
+ {5:-- INSERT --} |
+ ]],
+ })
+ end)
end)
describe('lua: nvim_buf_attach on_bytes', function()
@@ -426,14 +467,14 @@ describe('lua: nvim_buf_attach on_bytes', function()
it('opening lines', function()
local check_events = setup_eventcheck(verify, origlines)
- -- api.nvim_set_option_value('autoindent', true, {})
+ api.nvim_set_option_value('autoindent', false, {})
feed 'Go'
check_events {
{ 'test1', 'bytes', 1, 3, 7, 0, 114, 0, 0, 0, 1, 0, 1 },
}
feed '<cr>'
check_events {
- { 'test1', 'bytes', 1, 5, 7, 0, 114, 0, 0, 0, 1, 0, 1 },
+ { 'test1', 'bytes', 1, 4, 7, 0, 114, 0, 0, 0, 1, 0, 1 },
}
end)
@@ -447,7 +488,7 @@ describe('lua: nvim_buf_attach on_bytes', function()
feed '<cr>'
check_events {
{ 'test1', 'bytes', 1, 4, 7, 0, 114, 0, 4, 4, 0, 0, 0 },
- { 'test1', 'bytes', 1, 5, 7, 0, 114, 0, 0, 0, 1, 4, 5 },
+ { 'test1', 'bytes', 1, 4, 7, 0, 114, 0, 0, 0, 1, 4, 5 },
}
end)
@@ -477,7 +518,7 @@ describe('lua: nvim_buf_attach on_bytes', function()
api.nvim_set_option_value('filetype', 'c', {})
feed 'A<CR>'
check_events {
- { 'test1', 'bytes', 1, 4, 0, 10, 10, 0, 0, 0, 1, 3, 4 },
+ { 'test1', 'bytes', 1, 3, 0, 10, 10, 0, 0, 0, 1, 3, 4 },
}
feed '<ESC>'
@@ -493,7 +534,7 @@ describe('lua: nvim_buf_attach on_bytes', function()
feed '<CR>'
check_events {
{ 'test1', 'bytes', 1, 6, 1, 2, 13, 0, 1, 1, 0, 0, 0 },
- { 'test1', 'bytes', 1, 7, 1, 2, 13, 0, 0, 0, 1, 3, 4 },
+ { 'test1', 'bytes', 1, 6, 1, 2, 13, 0, 0, 0, 1, 3, 4 },
}
end)
diff --git a/test/functional/lua/fs_spec.lua b/test/functional/lua/fs_spec.lua
index a5cdfdc225..6e7811908b 100644
--- a/test/functional/lua/fs_spec.lua
+++ b/test/functional/lua/fs_spec.lua
@@ -36,6 +36,7 @@ local test_basename_dirname_eq = {
'c:/users/foo',
'c:/users/foo/bar.lua',
'c:/users/foo/bar/../',
+ '~/foo/bar\\baz',
}
local tests_windows_paths = {
@@ -70,26 +71,26 @@ describe('vim.fs', function()
it('works', function()
eq(test_build_dir, vim.fs.dirname(nvim_dir))
- --- @param paths string[]
- local function test_paths(paths)
+ ---@param paths string[]
+ ---@param is_win? boolean
+ local function test_paths(paths, is_win)
+ local gsub = is_win and [[:gsub('\\', '/')]] or ''
+ local code = string.format(
+ [[
+ local path = ...
+ return vim.fn.fnamemodify(path,':h')%s
+ ]],
+ gsub
+ )
+
for _, path in ipairs(paths) do
- eq(
- exec_lua(
- [[
- local path = ...
- return vim.fn.fnamemodify(path,':h'):gsub('\\', '/')
- ]],
- path
- ),
- vim.fs.dirname(path),
- path
- )
+ eq(exec_lua(code, path), vim.fs.dirname(path), path)
end
end
test_paths(test_basename_dirname_eq)
if is_os('win') then
- test_paths(tests_windows_paths)
+ test_paths(tests_windows_paths, true)
end
end)
end)
@@ -98,26 +99,26 @@ describe('vim.fs', function()
it('works', function()
eq(nvim_prog_basename, vim.fs.basename(nvim_prog))
- --- @param paths string[]
- local function test_paths(paths)
+ ---@param paths string[]
+ ---@param is_win? boolean
+ local function test_paths(paths, is_win)
+ local gsub = is_win and [[:gsub('\\', '/')]] or ''
+ local code = string.format(
+ [[
+ local path = ...
+ return vim.fn.fnamemodify(path,':t')%s
+ ]],
+ gsub
+ )
+
for _, path in ipairs(paths) do
- eq(
- exec_lua(
- [[
- local path = ...
- return vim.fn.fnamemodify(path,':t'):gsub('\\', '/')
- ]],
- path
- ),
- vim.fs.basename(path),
- path
- )
+ eq(exec_lua(code, path), vim.fs.basename(path), path)
end
end
test_paths(test_basename_dirname_eq)
if is_os('win') then
- test_paths(tests_windows_paths)
+ test_paths(tests_windows_paths, true)
end
end)
end)
@@ -284,9 +285,6 @@ describe('vim.fs', function()
end)
describe('normalize()', function()
- it('works with backward slashes', function()
- eq('C:/Users/jdoe', vim.fs.normalize('C:\\Users\\jdoe'))
- end)
it('removes trailing /', function()
eq('/home/user', vim.fs.normalize('/home/user/'))
end)
@@ -309,10 +307,27 @@ describe('vim.fs', function()
)
)
end)
+
+ it('works with UNC paths', function()
+ eq('//foo', vim.fs.normalize('//foo')) -- UNC path
+ eq('//foo/bar', vim.fs.normalize('//foo//bar////')) -- UNC path
+ eq('/foo', vim.fs.normalize('///foo')) -- Not a UNC path
+ eq('/', vim.fs.normalize('//')) -- Not a UNC path
+ eq('/', vim.fs.normalize('///')) -- Not a UNC path
+ eq('/foo/bar', vim.fs.normalize('/foo//bar////')) -- Not a UNC path
+ end)
+
if is_os('win') then
it('Last slash is not truncated from root drive', function()
eq('C:/', vim.fs.normalize('C:/'))
end)
+ it('converts backward slashes', function()
+ eq('C:/Users/jdoe', vim.fs.normalize('C:\\Users\\jdoe'))
+ end)
+ else
+ it('allows backslashes on unix-based os', function()
+ eq('/home/user/hello\\world', vim.fs.normalize('/home/user/hello\\world'))
+ end)
end
end)
end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 7ab009659b..8722c4dbb5 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -3007,25 +3007,65 @@ describe('lua stdlib', function()
end)
describe('vim.on_key', function()
- it('tracks keystrokes', function()
+ it('tracks Unicode input', function()
insert([[hello world ]])
exec_lua [[
keys = {}
+ typed = {}
- vim.on_key(function(buf)
+ vim.on_key(function(buf, typed_buf)
if buf:byte() == 27 then
buf = "<ESC>"
end
+ if typed_buf:byte() == 27 then
+ typed_buf = "<ESC>"
+ end
table.insert(keys, buf)
+ table.insert(typed, typed_buf)
end)
]]
- insert([[next 🤦 lines å ]])
+ insert([[next 🤦 lines å …]])
-- It has escape in the keys pressed
- eq('inext 🤦 lines å <ESC>', exec_lua [[return table.concat(keys, '')]])
+ eq('inext 🤦 lines å …<ESC>', exec_lua [[return table.concat(keys, '')]])
+ eq('inext 🤦 lines å …<ESC>', exec_lua [[return table.concat(typed, '')]])
+ end)
+
+ it('tracks input with modifiers', function()
+ exec_lua [[
+ keys = {}
+ typed = {}
+
+ vim.on_key(function(buf, typed_buf)
+ table.insert(keys, vim.fn.keytrans(buf))
+ table.insert(typed, vim.fn.keytrans(typed_buf))
+ end)
+ ]]
+
+ feed([[i<C-V><C-;><C-V><C-…><Esc>]])
+
+ eq('i<C-V><C-;><C-V><C-…><Esc>', exec_lua [[return table.concat(keys, '')]])
+ eq('i<C-V><C-;><C-V><C-…><Esc>', exec_lua [[return table.concat(typed, '')]])
+ end)
+
+ it('works with character find and Select mode', function()
+ insert('12345')
+
+ exec_lua [[
+ typed = {}
+
+ vim.cmd('snoremap # @')
+
+ vim.on_key(function(buf, typed_buf)
+ table.insert(typed, vim.fn.keytrans(typed_buf))
+ end)
+ ]]
+
+ feed('F3gHβγδεζ<Esc>gH…<Esc>gH#$%^')
+ eq('F3gHβγδεζ<Esc>gH…<Esc>gH#$%^', exec_lua [[return table.concat(typed, '')]])
end)
it('allows removing on_key listeners', function()
@@ -3087,23 +3127,29 @@ describe('lua stdlib', function()
eq('inext l', exec_lua [[ return table.concat(keys, '') ]])
end)
- it('processes mapped keys, not unmapped keys', function()
+ it('argument 1 is keys after mapping, argument 2 is typed keys', function()
exec_lua [[
keys = {}
+ typed = {}
vim.cmd("inoremap hello world")
- vim.on_key(function(buf)
+ vim.on_key(function(buf, typed_buf)
if buf:byte() == 27 then
buf = "<ESC>"
end
+ if typed_buf:byte() == 27 then
+ typed_buf = "<ESC>"
+ end
table.insert(keys, buf)
+ table.insert(typed, typed_buf)
end)
]]
insert('hello')
eq('iworld<ESC>', exec_lua [[return table.concat(keys, '')]])
+ eq('ihello<ESC>', exec_lua [[return table.concat(typed, '')]])
end)
it('can call vim.fn functions on Ctrl-C #17273', function()
diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua
index 0395d5ee16..08ec7b97cf 100644
--- a/test/functional/terminal/mouse_spec.lua
+++ b/test/functional/terminal/mouse_spec.lua
@@ -41,6 +41,7 @@ describe(':terminal mouse', function()
end)
it('will exit focus and trigger Normal mode mapping on mouse click', function()
+ feed([[<C-\><C-N>qri]])
command('let g:got_leftmouse = 0')
command('nnoremap <LeftMouse> <Cmd>let g:got_leftmouse = 1<CR>')
eq('t', eval('mode(1)'))
@@ -48,9 +49,12 @@ describe(':terminal mouse', function()
feed('<LeftMouse>')
eq('nt', eval('mode(1)'))
eq(1, eval('g:got_leftmouse'))
+ feed('q')
+ eq('i<LeftMouse>', eval('keytrans(@r)'))
end)
it('will exit focus and trigger Normal mode mapping on mouse click with modifier', function()
+ feed([[<C-\><C-N>qri]])
command('let g:got_ctrl_leftmouse = 0')
command('nnoremap <C-LeftMouse> <Cmd>let g:got_ctrl_leftmouse = 1<CR>')
eq('t', eval('mode(1)'))
@@ -58,6 +62,8 @@ describe(':terminal mouse', function()
feed('<C-LeftMouse>')
eq('nt', eval('mode(1)'))
eq(1, eval('g:got_ctrl_leftmouse'))
+ feed('q')
+ eq('i<C-LeftMouse>', eval('keytrans(@r)'))
end)
it('will exit focus on <C-\\> + mouse-scroll', function()
diff --git a/test/functional/vimscript/reltime_spec.lua b/test/functional/vimscript/reltime_spec.lua
index 7cdb78e4ce..fc4dd0d87b 100644
--- a/test/functional/vimscript/reltime_spec.lua
+++ b/test/functional/vimscript/reltime_spec.lua
@@ -1,6 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, eq, ok = helpers.clear, helpers.eq, helpers.ok
local neq, command, fn = helpers.neq, helpers.command, helpers.fn
+local matches = helpers.matches
local reltime, reltimestr, reltimefloat = fn.reltime, fn.reltimestr, fn.reltimefloat
describe('reltimestr(), reltimefloat()', function()
@@ -15,7 +16,7 @@ describe('reltimestr(), reltimefloat()', function()
neq('0.0', reltimestr(elapsed))
ok(reltimefloat(elapsed) > 0.0)
-- original vim test for < 0.1, but easily fails on travis
- ok(nil ~= string.match(reltimestr(elapsed), '0%.'))
+ matches('0%.', reltimestr(elapsed))
ok(reltimefloat(elapsed) < 1.0)
local same = reltime(now, now)
@@ -29,7 +30,7 @@ describe('reltimestr(), reltimefloat()', function()
neq('0.0', reltimestr(differs))
ok(reltimefloat(differs) > 0.0)
-- original vim test for < 0.1, but easily fails on travis
- ok(nil ~= string.match(reltimestr(differs), '0%.'))
+ matches('0%.', reltimestr(differs))
ok(reltimefloat(differs) < 1.0)
end)
diff --git a/test/functional/vimscript/server_spec.lua b/test/functional/vimscript/server_spec.lua
index 360fcf0dfe..c6c9e9c0ab 100644
--- a/test/functional/vimscript/server_spec.lua
+++ b/test/functional/vimscript/server_spec.lua
@@ -100,14 +100,14 @@ describe('server', function()
local s = fn.serverstart('127.0.0.1:0') -- assign random port
if #s > 0 then
- assert(string.match(s, '127.0.0.1:%d+'))
+ matches('127.0.0.1:%d+', s)
eq(s, fn.serverlist()[1])
clear_serverlist()
end
s = fn.serverstart('127.0.0.1:') -- assign random port
if #s > 0 then
- assert(string.match(s, '127.0.0.1:%d+'))
+ matches('127.0.0.1:%d+', s)
eq(s, fn.serverlist()[1])
clear_serverlist()
end
diff --git a/test/old/testdir/test_autocmd.vim b/test/old/testdir/test_autocmd.vim
index f1040b4b35..61de6775fb 100644
--- a/test/old/testdir/test_autocmd.vim
+++ b/test/old/testdir/test_autocmd.vim
@@ -3957,4 +3957,101 @@ func Test_implicit_session()
call delete(expected)
endfunc
+" Test TextChangedI and TextChanged
+func Test_Changed_ChangedI_2()
+ CheckRunVimInTerminal
+ call writefile(['one', 'two', 'three'], 'XTextChangedI2', 'D')
+ let before =<< trim END
+ autocmd TextChanged,TextChangedI * call writefile([b:changedtick], 'XTextChangedI3')
+ nnoremap <CR> o<Esc>
+ call writefile([], 'XTextChangedI3')
+ END
+
+ call writefile(before, 'Xinit', 'D')
+ let buf = RunVimInTerminal('-S Xinit XtextChangedI2', {})
+ call term_sendkeys(buf, "\<cr>")
+ call term_wait(buf)
+ call StopVimInTerminal(buf)
+ call assert_equal(['4'], readfile('XTextChangedI3'))
+
+ call delete('XTextChangedI3')
+endfunc
+
+" Test that filetype detection still works when SwapExists autocommand sets
+" filetype in another buffer.
+func Test_SwapExists_set_other_buf_filetype()
+ let lines =<< trim END
+ set nocompatible directory=.
+ filetype on
+
+ let g:buf = bufnr()
+ new
+
+ func SwapExists()
+ let v:swapchoice = 'o'
+ call setbufvar(g:buf, '&filetype', 'text')
+ endfunc
+
+ func SafeState()
+ edit <script>
+ redir! > XftSwapExists.out
+ set readonly? filetype?
+ redir END
+ qall!
+ endfunc
+
+ autocmd SwapExists * ++nested call SwapExists()
+ autocmd SafeState * ++nested ++once call SafeState()
+ END
+ call writefile(lines, 'XftSwapExists.vim', 'D')
+
+ new XftSwapExists.vim
+ if RunVim('', '', ' -S XftSwapExists.vim')
+ call assert_equal(
+ \ ['', ' readonly', ' filetype=vim'],
+ \ readfile('XftSwapExists.out'))
+ call delete('XftSwapExists.out')
+ endif
+
+ bwipe!
+endfunc
+
+" Test that file is not marked as modified when SwapExists autocommand sets
+" 'modified' in another buffer.
+func Test_SwapExists_set_other_buf_modified()
+ let lines =<< trim END
+ set nocompatible directory=.
+
+ let g:buf = bufnr()
+ new
+
+ func SwapExists()
+ let v:swapchoice = 'o'
+ call setbufvar(g:buf, '&modified', 1)
+ endfunc
+
+ func SafeState()
+ edit <script>
+ redir! > XmodSwapExists.out
+ set readonly? modified?
+ redir END
+ qall!
+ endfunc
+
+ autocmd SwapExists * ++nested call SwapExists()
+ autocmd SafeState * ++nested ++once call SafeState()
+ END
+ call writefile(lines, 'XmodSwapExists.vim', 'D')
+
+ new XmodSwapExists.vim
+ if RunVim('', '', ' -S XmodSwapExists.vim')
+ call assert_equal(
+ \ ['', ' readonly', 'nomodified'],
+ \ readfile('XmodSwapExists.out'))
+ call delete('XmodSwapExists.out')
+ endif
+
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_conceal.vim b/test/old/testdir/test_conceal.vim
index 84b931f39d..df20654f12 100644
--- a/test/old/testdir/test_conceal.vim
+++ b/test/old/testdir/test_conceal.vim
@@ -197,6 +197,7 @@ endfunc
" Same as Test_conceal_wrapped_cursorline_wincolor(), but with 'rightleft'.
func Test_conceal_wrapped_cursorline_wincolor_rightleft()
+ CheckFeature rightleft
CheckScreendump
let code =<< trim [CODE]
diff --git a/test/old/testdir/test_normal.vim b/test/old/testdir/test_normal.vim
index 937f18aa69..26270fddd2 100644
--- a/test/old/testdir/test_normal.vim
+++ b/test/old/testdir/test_normal.vim
@@ -4184,21 +4184,29 @@ func Test_normal34_zet_large()
norm! z9765405999999999999
endfunc
-" Test for { and } paragraph movements and Ctrl-B in buffer with a single line
-func Test_single_line_scroll()
- CheckFeature textprop
-
+" Test for { and } paragraph movements in a single line
+func Test_brace_single_line()
new
call setline(1, ['foobar one two three'])
- let vt = 'virt_above'
- call prop_type_add(vt, {'highlight': 'IncSearch'})
- call prop_add(1, 0, {'type': vt, 'text': '---', 'text_align': 'above'})
1
norm! 0}
call assert_equal([0, 1, 20, 0], getpos('.'))
norm! {
call assert_equal([0, 1, 1, 0], getpos('.'))
+ bw!
+endfunc
+
+" Test for Ctrl-B/Ctrl-U in buffer with a single line
+func Test_single_line_scroll()
+ CheckFeature textprop
+
+ new
+ call setline(1, ['foobar one two three'])
+ let vt = 'virt_above'
+ call prop_type_add(vt, {'highlight': 'IncSearch'})
+ call prop_add(1, 0, {'type': vt, 'text': '---', 'text_align': 'above'})
+ call cursor(1, 1)
" Ctrl-B/Ctrl-U scroll up with hidden "above" virtual text.
set smoothscroll
@@ -4213,6 +4221,7 @@ func Test_single_line_scroll()
set smoothscroll&
bw!
+ call prop_type_delete(vt)
endfunc
" vim: shiftwidth=2 sts=2 expandtab nofoldenable
diff --git a/test/old/testdir/test_perl.vim b/test/old/testdir/test_perl.vim
index 37b1d08b1a..c08a042dae 100644
--- a/test/old/testdir/test_perl.vim
+++ b/test/old/testdir/test_perl.vim
@@ -94,6 +94,7 @@ func Test_buffer_Number()
endfunc
func Test_window_Cursor()
+ throw 'skipped: flaky '
new
call setline(1, ['line1', 'line2'])
perl $curwin->Cursor(2, 3)
@@ -104,7 +105,7 @@ func Test_window_Cursor()
endfunc
func Test_window_SetHeight()
- throw 'skipped: very flaky '
+ throw 'skipped: flaky '
new
perl $curwin->SetHeight(2)
call assert_equal(2, winheight(0))
diff --git a/test/old/testdir/test_registers.vim b/test/old/testdir/test_registers.vim
index e113bd9e75..1a25844ad3 100644
--- a/test/old/testdir/test_registers.vim
+++ b/test/old/testdir/test_registers.vim
@@ -214,6 +214,58 @@ func Test_recording_with_select_mode()
bwipe!
endfunc
+func Run_test_recording_with_select_mode_utf8()
+ new
+
+ " Test with different text lengths: 5, 7, 9, 11, 13, 15, to check that
+ " a character isn't split between two buffer blocks.
+ for s in ['12345', '口=口', '口口口', '口=口=口', '口口=口口', '口口口口口']
+ " 0x80 is K_SPECIAL
+ " 0x9B is CSI
+ " 哦: 0xE5 0x93 0xA6
+ " 洛: 0xE6 0xB4 0x9B
+ " 固: 0xE5 0x9B 0xBA
+ " 四: 0xE5 0x9B 0x9B
+ " 最: 0xE6 0x9C 0x80
+ " 倒: 0xE5 0x80 0x92
+ " 倀: 0xE5 0x80 0x80
+ for c in ['哦', '洛', '固', '四', '最', '倒', '倀']
+ call setline(1, 'asdf')
+ call feedkeys($"qacc{s}\<Esc>gH{c}\<Esc>q", "tx")
+ call assert_equal(c, getline(1))
+ call assert_equal($"cc{s}\<Esc>gH{c}\<Esc>", @a)
+ call setline(1, 'asdf')
+ normal! @a
+ call assert_equal(c, getline(1))
+
+ " Test with Shift modifier.
+ let shift_c = eval($'"\<S-{c}>"')
+ call setline(1, 'asdf')
+ call feedkeys($"qacc{s}\<Esc>gH{shift_c}\<Esc>q", "tx")
+ call assert_equal(c, getline(1))
+ call assert_equal($"cc{s}\<Esc>gH{shift_c}\<Esc>", @a)
+ call setline(1, 'asdf')
+ normal! @a
+ call assert_equal(c, getline(1))
+ endfor
+ endfor
+
+ bwipe!
+endfunc
+
+func Test_recording_with_select_mode_utf8()
+ call Run_test_recording_with_select_mode_utf8()
+endfunc
+
+" This must be done as one of the last tests, because it starts the GUI, which
+" cannot be undone.
+func Test_zz_recording_with_select_mode_utf8_gui()
+ CheckCanRunGui
+
+ gui -f
+ call Run_test_recording_with_select_mode_utf8()
+endfunc
+
" Test for executing the last used register (@)
func Test_last_used_exec_reg()
" Test for the @: command
diff --git a/test/old/testdir/test_scroll_opt.vim b/test/old/testdir/test_scroll_opt.vim
index fbc714d9cc..575ce0c6b5 100644
--- a/test/old/testdir/test_scroll_opt.vim
+++ b/test/old/testdir/test_scroll_opt.vim
@@ -741,6 +741,7 @@ func Test_smoothscroll_mouse_pos()
let &mouse = save_mouse
"let &term = save_term
"let &ttymouse = save_ttymouse
+ bwipe!
endfunc
" this was dividing by zero
@@ -1002,9 +1003,8 @@ func Test_smoothscroll_textoff_small_winwidth()
endfunc
func Test_smoothscroll_page()
- set smoothscroll
-
- 10split | 40vsplit
+ call NewWindow(10, 40)
+ setlocal smoothscroll
call setline(1, 'abcde '->repeat(150))
exe "norm! \<C-F>"
@@ -1041,7 +1041,7 @@ func Test_smoothscroll_page()
exe "norm! \<C-U>"
call assert_equal(0, winsaveview().skipcol)
- set smoothscroll&
+ bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_utf8.vim b/test/old/testdir/test_utf8.vim
index a5a9624ec3..920000e2c7 100644
--- a/test/old/testdir/test_utf8.vim
+++ b/test/old/testdir/test_utf8.vim
@@ -292,55 +292,4 @@ func Test_print_overlong()
bwipe!
endfunc
-func Test_recording_with_select_mode_utf8()
- call Run_test_recording_with_select_mode_utf8()
-endfunc
-
-func Run_test_recording_with_select_mode_utf8()
- new
-
- " No escaping
- call feedkeys("qacc12345\<Esc>gH哦\<Esc>q", "tx")
- call assert_equal("哦", getline(1))
- call assert_equal("cc12345\<Esc>gH哦\<Esc>", @a)
- call setline(1, 'asdf')
- normal! @a
- call assert_equal("哦", getline(1))
-
- " 固 is 0xE5 0x9B 0xBA where 0x9B is CSI
- call feedkeys("qacc12345\<Esc>gH固\<Esc>q", "tx")
- call assert_equal("固", getline(1))
- call assert_equal("cc12345\<Esc>gH固\<Esc>", @a)
- call setline(1, 'asdf')
- normal! @a
- call assert_equal("固", getline(1))
-
- " 四 is 0xE5 0x9B 0x9B where 0x9B is CSI
- call feedkeys("qacc12345\<Esc>gH四\<Esc>q", "tx")
- call assert_equal("四", getline(1))
- call assert_equal("cc12345\<Esc>gH四\<Esc>", @a)
- call setline(1, 'asdf')
- normal! @a
- call assert_equal("四", getline(1))
-
- " 倒 is 0xE5 0x80 0x92 where 0x80 is K_SPECIAL
- call feedkeys("qacc12345\<Esc>gH倒\<Esc>q", "tx")
- call assert_equal("倒", getline(1))
- call assert_equal("cc12345\<Esc>gH倒\<Esc>", @a)
- call setline(1, 'asdf')
- normal! @a
- call assert_equal("倒", getline(1))
-
- bwipe!
-endfunc
-
-" This must be done as one of the last tests, because it starts the GUI, which
-" cannot be undone.
-func Test_zz_recording_with_select_mode_utf8_gui()
- CheckCanRunGui
-
- gui -f
- call Run_test_recording_with_select_mode_utf8()
-endfunc
-
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/unit/eval/typval_spec.lua b/test/unit/eval/typval_spec.lua
index 1cd5647a9e..a775bb48b4 100644
--- a/test/unit/eval/typval_spec.lua
+++ b/test/unit/eval/typval_spec.lua
@@ -3223,7 +3223,7 @@ describe('typval.c', function()
end)
end)
describe('lnum()', function()
- itp('works', function()
+ pending('works (skip due to flakiness)', function()
for _, v in ipairs({
{ lib.VAR_NUMBER, { v_number = 42 }, nil, 42 },
{ lib.VAR_STRING, { v_string = to_cstr('100500') }, nil, 100500 },