aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/scripts/close_unresponsive.js19
-rw-r--r--.github/workflows/api-docs-check.yml18
-rw-r--r--.github/workflows/api-docs.yml42
-rw-r--r--.github/workflows/build.yml36
-rw-r--r--.github/workflows/issue-open-check.yml34
-rw-r--r--.github/workflows/test.yml21
-rw-r--r--CMakeLists.txt34
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--MAINTAIN.md4
-rw-r--r--Makefile2
-rw-r--r--cmake.config/CMakeLists.txt7
-rw-r--r--cmake.config/iwyu/mapping.imp1
-rw-r--r--cmake.config/versiondef.h.in2
-rw-r--r--cmake.config/versiondef_old.h.in21
-rw-r--r--cmake.deps/CMakeLists.txt81
-rw-r--r--cmake.deps/cmake/BuildLua.cmake9
-rw-r--r--cmake.deps/cmake/BuildLuajit.cmake11
-rw-r--r--cmake.deps/cmake/BuildLuarocks.cmake137
-rw-r--r--cmake.deps/cmake/BuildLuv.cmake9
-rw-r--r--cmake.deps/cmake/BuildMsgpack.cmake8
-rw-r--r--cmake.deps/cmake/CopyFilesGlob.cmake2
-rw-r--r--cmake.deps/deps.txt23
-rw-r--r--cmake.packaging/CMakeLists.txt3
-rw-r--r--cmake/BuildLuarocks.cmake109
-rw-r--r--cmake/CheckUncrustifyVersion.cmake13
-rw-r--r--cmake/ConvertPo.cmake2
-rw-r--r--cmake/Deps.cmake54
-rw-r--r--cmake/FindLibluv.cmake14
-rw-r--r--cmake/FindLibuv.cmake8
-rw-r--r--cmake/FindLuajit.cmake3
-rw-r--r--cmake/FindLuv.cmake14
-rw-r--r--cmake/FindTreesitter.cmake20
-rw-r--r--cmake/Format.cmake6
-rw-r--r--cmake/InstallHelpers.cmake3
-rw-r--r--cmake/LuaHelpers.cmake14
-rw-r--r--cmake/RunTests.cmake4
-rw-r--r--cmake/Util.cmake11
-rwxr-xr-xcontrib/asan.sh3
-rw-r--r--contrib/flake.nix1
-rw-r--r--runtime/autoload/netrw.vim8
-rw-r--r--runtime/autoload/netrwSettings.vim2
-rw-r--r--runtime/doc/api.txt61
-rw-r--r--runtime/doc/autocmd.txt2
-rw-r--r--runtime/doc/builtin.txt15
-rw-r--r--runtime/doc/cmdline.txt6
-rw-r--r--runtime/doc/deprecated.txt6
-rw-r--r--runtime/doc/editing.txt2
-rw-r--r--runtime/doc/eval.txt12
-rw-r--r--runtime/doc/filetype.txt1
-rw-r--r--runtime/doc/ft_raku.txt2
-rw-r--r--runtime/doc/helphelp.txt2
-rw-r--r--runtime/doc/if_pyth.txt42
-rw-r--r--runtime/doc/indent.txt2
-rw-r--r--runtime/doc/insert.txt4
-rw-r--r--runtime/doc/intro.txt2
-rw-r--r--runtime/doc/job_control.txt3
-rw-r--r--runtime/doc/lsp.txt27
-rw-r--r--runtime/doc/lua-guide.txt4
-rw-r--r--runtime/doc/lua.txt30
-rw-r--r--runtime/doc/luvref.txt114
-rw-r--r--runtime/doc/map.txt25
-rw-r--r--runtime/doc/news.txt34
-rw-r--r--runtime/doc/options.txt30
-rw-r--r--runtime/doc/pi_netrw.txt54
-rw-r--r--runtime/doc/pi_tar.txt4
-rw-r--r--runtime/doc/provider.txt2
-rw-r--r--runtime/doc/quickfix.txt2
-rw-r--r--runtime/doc/repeat.txt3
-rw-r--r--runtime/doc/sign.txt6
-rw-r--r--runtime/doc/spell.txt2
-rw-r--r--runtime/doc/syntax.txt6
-rw-r--r--runtime/doc/testing.txt25
-rw-r--r--runtime/doc/treesitter.txt56
-rw-r--r--runtime/doc/ui.txt6
-rw-r--r--runtime/doc/usr_01.txt2
-rw-r--r--runtime/doc/visual.txt2
-rw-r--r--runtime/ftplugin/luau.vim14
-rw-r--r--runtime/ftplugin/usd.vim18
-rw-r--r--runtime/indent/dts.vim63
-rw-r--r--runtime/indent/luau.vim14
-rw-r--r--runtime/indent/testdir/dts.in46
-rw-r--r--runtime/indent/testdir/dts.ok46
-rw-r--r--runtime/lua/_vim9script.lua2
-rw-r--r--runtime/lua/man.lua9
-rw-r--r--runtime/lua/vim/_editor.lua2
-rw-r--r--runtime/lua/vim/_inspector.lua2
-rw-r--r--runtime/lua/vim/filetype.lua7
-rw-r--r--runtime/lua/vim/filetype/detect.lua22
-rw-r--r--runtime/lua/vim/fs.lua18
-rw-r--r--runtime/lua/vim/lsp.lua22
-rw-r--r--runtime/lua/vim/lsp/_watchfiles.lua17
-rw-r--r--runtime/lua/vim/lsp/buf.lua2
-rw-r--r--runtime/lua/vim/lsp/handlers.lua2
-rw-r--r--runtime/lua/vim/lsp/util.lua30
-rw-r--r--runtime/lua/vim/shared.lua8
-rw-r--r--runtime/lua/vim/treesitter.lua10
-rw-r--r--runtime/lua/vim/treesitter/_fold.lua4
-rw-r--r--runtime/lua/vim/treesitter/_meta.lua18
-rw-r--r--runtime/lua/vim/treesitter/_range.lua38
-rw-r--r--runtime/lua/vim/treesitter/language.lua5
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua73
-rw-r--r--runtime/lua/vim/treesitter/query.lua45
-rw-r--r--runtime/lua/vim/version.lua2
-rw-r--r--runtime/menu.vim6
-rw-r--r--runtime/pack/dist/opt/termdebug/plugin/termdebug.vim6
-rw-r--r--runtime/plugin/netrwPlugin.vim2
-rw-r--r--runtime/queries/c/highlights.scm17
-rw-r--r--runtime/queries/lua/highlights.scm10
-rw-r--r--runtime/queries/lua/injections.scm10
-rw-r--r--runtime/queries/query/highlights.scm8
-rw-r--r--runtime/queries/vim/highlights.scm2
-rw-r--r--runtime/queries/vimdoc/highlights.scm8
-rw-r--r--runtime/syntax/checkhealth.vim2
-rw-r--r--runtime/syntax/dts.vim5
-rw-r--r--runtime/syntax/luau.vim15
-rw-r--r--runtime/syntax/nasm.vim72
-rw-r--r--runtime/syntax/xpm.vim181
-rwxr-xr-xscripts/bump_deps.lua24
-rwxr-xr-xscripts/vim-patch.sh2
-rwxr-xr-xsrc/clint.py1
-rw-r--r--src/klib/khash.h135
-rw-r--r--src/nvim/CMakeLists.txt38
-rw-r--r--src/nvim/README.md3
-rw-r--r--src/nvim/api/autocmd.c16
-rw-r--r--src/nvim/api/buffer.c2
-rw-r--r--src/nvim/api/command.c5
-rw-r--r--src/nvim/api/deprecated.c220
-rw-r--r--src/nvim/api/extmark.c26
-rw-r--r--src/nvim/api/extmark.h1
-rw-r--r--src/nvim/api/options.c218
-rw-r--r--src/nvim/api/options.h1
-rw-r--r--src/nvim/api/private/converter.h2
-rw-r--r--src/nvim/api/private/helpers.c10
-rw-r--r--src/nvim/api/private/helpers.h16
-rw-r--r--src/nvim/api/ui.c4
-rw-r--r--src/nvim/api/vim.c8
-rw-r--r--src/nvim/api/vimscript.c10
-rw-r--r--src/nvim/api/win_config.c8
-rw-r--r--src/nvim/arglist.h2
-rw-r--r--src/nvim/autocmd.c24
-rw-r--r--src/nvim/buffer.c61
-rw-r--r--src/nvim/buffer_defs.h3
-rw-r--r--src/nvim/bufwrite.c16
-rw-r--r--src/nvim/change.c26
-rw-r--r--src/nvim/channel.c16
-rw-r--r--src/nvim/channel.h2
-rw-r--r--src/nvim/charset.c15
-rw-r--r--src/nvim/charset.h2
-rw-r--r--src/nvim/cmdexpand.h2
-rw-r--r--src/nvim/cmdhist.c7
-rw-r--r--src/nvim/cmdhist.h1
-rw-r--r--src/nvim/cursor_shape.c4
-rw-r--r--src/nvim/decoration.c7
-rw-r--r--src/nvim/decoration.h4
-rw-r--r--src/nvim/drawline.c336
-rw-r--r--src/nvim/drawscreen.c9
-rw-r--r--src/nvim/edit.c17
-rw-r--r--src/nvim/eval.c17
-rw-r--r--src/nvim/eval/decode.h4
-rw-r--r--src/nvim/eval/executor.h2
-rw-r--r--src/nvim/eval/funcs.h1
-rw-r--r--src/nvim/eval/gc.h1
-rw-r--r--src/nvim/eval/typval.c22
-rw-r--r--src/nvim/eval/typval.h4
-rw-r--r--src/nvim/eval/typval_encode.h2
-rw-r--r--src/nvim/eval/userfunc.c18
-rw-r--r--src/nvim/eval/userfunc.h1
-rw-r--r--src/nvim/event/process.h1
-rw-r--r--src/nvim/ex_cmds.c30
-rw-r--r--src/nvim/ex_cmds.h1
-rw-r--r--src/nvim/ex_cmds_defs.h2
-rw-r--r--src/nvim/ex_docmd.c28
-rw-r--r--src/nvim/ex_getln.c20
-rw-r--r--src/nvim/ex_getln.h1
-rw-r--r--src/nvim/extmark.c25
-rw-r--r--src/nvim/fileio.c30
-rw-r--r--src/nvim/fileio.h1
-rw-r--r--src/nvim/generators/gen_ex_cmds.lua1
-rw-r--r--src/nvim/getchar.c51
-rw-r--r--src/nvim/globals.h7
-rw-r--r--src/nvim/grid.c3
-rw-r--r--src/nvim/help.c1
-rw-r--r--src/nvim/highlight.c53
-rw-r--r--src/nvim/highlight_group.c19
-rw-r--r--src/nvim/lua/converter.h2
-rw-r--r--src/nvim/lua/executor.c97
-rw-r--r--src/nvim/lua/executor.h4
-rw-r--r--src/nvim/lua/secure.c118
-rw-r--r--src/nvim/lua/secure.h12
-rw-r--r--src/nvim/lua/treesitter.c123
-rw-r--r--src/nvim/main.c18
-rw-r--r--src/nvim/map.c109
-rw-r--r--src/nvim/map.h104
-rw-r--r--src/nvim/map_defs.h12
-rw-r--r--src/nvim/mapping.c10
-rw-r--r--src/nvim/mark_defs.h2
-rw-r--r--src/nvim/marktree.c6
-rw-r--r--src/nvim/marktree.h1
-rw-r--r--src/nvim/mbyte.c18
-rw-r--r--src/nvim/mbyte.h2
-rw-r--r--src/nvim/memory.c2
-rw-r--r--src/nvim/menu.c4
-rw-r--r--src/nvim/message.c6
-rw-r--r--src/nvim/move.c144
-rw-r--r--src/nvim/msgpack_rpc/channel.c53
-rw-r--r--src/nvim/msgpack_rpc/channel_defs.h2
-rw-r--r--src/nvim/normal.c11
-rw-r--r--src/nvim/ops.c20
-rw-r--r--src/nvim/ops.h5
-rw-r--r--src/nvim/option.c6
-rw-r--r--src/nvim/option_defs.h2
-rw-r--r--src/nvim/optionstr.c12
-rw-r--r--src/nvim/os/process.c2
-rw-r--r--src/nvim/os/pty_process_win.c1
-rw-r--r--src/nvim/os/stdpaths.c2
-rw-r--r--src/nvim/os/time.c2
-rw-r--r--src/nvim/plines.c85
-rw-r--r--src/nvim/plines.h6
-rw-r--r--src/nvim/popupmenu.c10
-rw-r--r--src/nvim/runtime.c37
-rw-r--r--src/nvim/runtime.h1
-rw-r--r--src/nvim/search.c4
-rw-r--r--src/nvim/search.h1
-rw-r--r--src/nvim/shada.c214
-rw-r--r--src/nvim/spell.c39
-rw-r--r--src/nvim/spellfile.c2
-rw-r--r--src/nvim/spellsuggest.c2
-rw-r--r--src/nvim/statusline.c4
-rw-r--r--src/nvim/strings.c37
-rw-r--r--src/nvim/strings.h2
-rw-r--r--src/nvim/tag.c21
-rw-r--r--src/nvim/terminal.c23
-rw-r--r--src/nvim/testing.c4
-rw-r--r--src/nvim/testing.h2
-rw-r--r--src/nvim/textobject.c3
-rw-r--r--src/nvim/tui/input.c21
-rw-r--r--src/nvim/tui/tui.c35
-rw-r--r--src/nvim/ui.c20
-rw-r--r--src/nvim/ui_client.c4
-rw-r--r--src/nvim/undo.c9
-rw-r--r--src/nvim/usercmd.c22
-rw-r--r--src/nvim/viml/parser/expressions.c2
-rw-r--r--src/nvim/viml/parser/expressions.h1
-rw-r--r--src/nvim/window.c63
-rw-r--r--src/nvim/window.h6
-rw-r--r--src/uncrustify.cfg57
-rw-r--r--test/CMakeLists.txt20
-rw-r--r--test/README.md2
-rw-r--r--test/busted/outputHandlers/nvim.lua8
-rw-r--r--test/busted_runner.lua13
-rw-r--r--test/functional/api/buffer_spec.lua24
-rw-r--r--test/functional/api/extmark_spec.lua4
-rw-r--r--test/functional/api/highlight_spec.lua9
-rw-r--r--test/functional/api/keymap_spec.lua45
-rw-r--r--test/functional/api/vim_spec.lua90
-rw-r--r--test/functional/api/window_spec.lua26
-rw-r--r--test/functional/autocmd/autocmd_spec.lua2
-rw-r--r--test/functional/autocmd/cursorhold_spec.lua6
-rw-r--r--test/functional/autocmd/termxx_spec.lua14
-rw-r--r--test/functional/core/spellfile_spec.lua20
-rw-r--r--test/functional/core/startup_spec.lua6
-rw-r--r--test/functional/editor/K_spec.lua2
-rw-r--r--test/functional/editor/completion_spec.lua2
-rw-r--r--test/functional/editor/mode_cmdline_spec.lua2
-rw-r--r--test/functional/ex_cmds/append_spec.lua3
-rw-r--r--test/functional/ex_cmds/cmd_map_spec.lua4
-rw-r--r--test/functional/ex_cmds/ls_spec.lua2
-rw-r--r--test/functional/ex_cmds/make_spec.lua4
-rw-r--r--test/functional/ex_cmds/map_spec.lua2
-rw-r--r--test/functional/ex_cmds/mksession_spec.lua14
-rw-r--r--test/functional/ex_cmds/source_spec.lua2
-rw-r--r--test/functional/ex_cmds/verbose_spec.lua4
-rw-r--r--test/functional/ex_cmds/write_spec.lua8
-rw-r--r--test/functional/legacy/012_directory_spec.lua13
-rw-r--r--test/functional/legacy/autocmd_option_spec.lua12
-rw-r--r--test/functional/legacy/buffer_spec.lua2
-rw-r--r--test/functional/legacy/cmdline_spec.lua14
-rw-r--r--test/functional/legacy/display_spec.lua112
-rw-r--r--test/functional/legacy/filechanged_spec.lua4
-rw-r--r--test/functional/legacy/messages_spec.lua6
-rw-r--r--test/functional/legacy/normal_spec.lua41
-rw-r--r--test/functional/legacy/scroll_opt_spec.lua168
-rw-r--r--test/functional/legacy/vimscript_spec.lua2
-rw-r--r--test/functional/lua/buffer_updates_spec.lua12
-rw-r--r--test/functional/lua/command_line_completion_spec.lua8
-rw-r--r--test/functional/lua/filetype_spec.lua2
-rw-r--r--test/functional/lua/fs_spec.lua15
-rw-r--r--test/functional/lua/inspector_spec.lua6
-rw-r--r--test/functional/lua/luaeval_spec.lua4
-rw-r--r--test/functional/lua/overrides_spec.lua2
-rw-r--r--test/functional/lua/runtime_spec.lua32
-rw-r--r--test/functional/lua/secure_spec.lua4
-rw-r--r--test/functional/lua/vim_spec.lua60
-rw-r--r--test/functional/options/defaults_spec.lua64
-rw-r--r--test/functional/options/num_options_spec.lua22
-rw-r--r--test/functional/plugin/editorconfig_spec.lua3
-rw-r--r--test/functional/plugin/lsp/incremental_sync_spec.lua2
-rw-r--r--test/functional/plugin/lsp_spec.lua114
-rw-r--r--test/functional/plugin/man_spec.lua32
-rw-r--r--test/functional/plugin/shada_spec.lua30
-rw-r--r--test/functional/provider/perl_spec.lua4
-rw-r--r--test/functional/provider/ruby_spec.lua3
-rw-r--r--test/functional/shada/buffers_spec.lua8
-rw-r--r--test/functional/shada/history_spec.lua8
-rw-r--r--test/functional/shada/shada_spec.lua34
-rw-r--r--test/functional/terminal/buffer_spec.lua3
-rw-r--r--test/functional/terminal/edit_spec.lua6
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua10
-rw-r--r--test/functional/terminal/mouse_spec.lua4
-rw-r--r--test/functional/terminal/scrollback_spec.lua46
-rw-r--r--test/functional/terminal/tui_spec.lua42
-rw-r--r--test/functional/terminal/window_spec.lua4
-rw-r--r--test/functional/terminal/window_split_tab_spec.lua4
-rw-r--r--test/functional/treesitter/parser_spec.lua58
-rw-r--r--test/functional/ui/cmdline_highlight_spec.lua2
-rw-r--r--test/functional/ui/cursor_spec.lua8
-rw-r--r--test/functional/ui/decorations_spec.lua946
-rw-r--r--test/functional/ui/float_spec.lua115
-rw-r--r--test/functional/ui/fold_spec.lua86
-rw-r--r--test/functional/ui/inccommand_spec.lua23
-rw-r--r--test/functional/ui/inccommand_user_spec.lua2
-rw-r--r--test/functional/ui/messages_spec.lua2
-rw-r--r--test/functional/ui/mouse_spec.lua26
-rw-r--r--test/functional/ui/multigrid_spec.lua6
-rw-r--r--test/functional/ui/quickfix_spec.lua2
-rw-r--r--test/functional/ui/screen_basic_spec.lua131
-rw-r--r--test/functional/ui/spell_spec.lua205
-rw-r--r--test/functional/ui/statuscolumn_spec.lua30
-rw-r--r--test/functional/ui/statusline_spec.lua56
-rw-r--r--test/functional/ui/title_spec.lua138
-rw-r--r--test/functional/ui/wildmode_spec.lua20
-rw-r--r--test/functional/ui/winbar_spec.lua31
-rw-r--r--test/functional/vimscript/api_functions_spec.lua4
-rw-r--r--test/functional/vimscript/buf_functions_spec.lua22
-rw-r--r--test/functional/vimscript/input_spec.lua4
-rw-r--r--test/functional/vimscript/json_functions_spec.lua2
-rw-r--r--test/functional/vimscript/system_spec.lua4
-rw-r--r--test/old/testdir/test_charsearch.vim2
-rw-r--r--test/old/testdir/test_charsearch_utf8.vim7
-rw-r--r--test/old/testdir/test_cmdline.vim12
-rw-r--r--test/old/testdir/test_cmdwin.vim67
-rw-r--r--test/old/testdir/test_display.vim51
-rw-r--r--test/old/testdir/test_ex_mode.vim4
-rw-r--r--test/old/testdir/test_exit.vim12
-rw-r--r--test/old/testdir/test_expr.vim3
-rw-r--r--test/old/testdir/test_filetype.vim42
-rw-r--r--test/old/testdir/test_functions.vim4
-rw-r--r--test/old/testdir/test_gf.vim61
-rw-r--r--test/old/testdir/test_mapping.vim482
-rw-r--r--test/old/testdir/test_normal.vim41
-rw-r--r--test/old/testdir/test_python2.vim195
-rw-r--r--test/old/testdir/test_pyx2.vim103
-rw-r--r--test/old/testdir/test_scroll_opt.vim108
-rw-r--r--test/old/testdir/test_spell.vim77
-rw-r--r--test/old/testdir/test_utf8.vim6
355 files changed, 6775 insertions, 3318 deletions
diff --git a/.github/scripts/close_unresponsive.js b/.github/scripts/close_unresponsive.js
index b7a92207ba..f0e8bbe93e 100644
--- a/.github/scripts/close_unresponsive.js
+++ b/.github/scripts/close_unresponsive.js
@@ -19,13 +19,18 @@ module.exports = async ({ github, context }) => {
const numbers = issues.data.map((e) => e.number);
for (const number of numbers) {
- const timeline = await github.rest.issues.listEventsForTimeline({
- owner: owner,
- repo: repo,
- issue_number: number,
- });
- const data = timeline.data.filter(labeledEvent);
- const latest_response_label = data[data.length - 1];
+ const events = await github.paginate(
+ github.rest.issues.listEventsForTimeline,
+ {
+ owner: owner,
+ repo: repo,
+ issue_number: number,
+ },
+ (response) => response.data.filter(labeledEvent)
+ );
+
+ const latest_response_label = events[events.length - 1];
+
const created_at = new Date(latest_response_label.created_at);
const now = new Date();
const diff = now - created_at;
diff --git a/.github/workflows/api-docs-check.yml b/.github/workflows/api-docs-check.yml
deleted file mode 100644
index 0a57df7c33..0000000000
--- a/.github/workflows/api-docs-check.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-name: Missing API docs
-on:
- pull_request:
- branches-ignore:
- - 'marvim/api-doc-update**'
- paths:
- - 'src/nvim/api/*.[ch]'
- - 'runtime/lua/**.lua'
- - 'runtime/doc/**'
-
-jobs:
- call-regen-api-docs:
- permissions:
- contents: write
- pull-requests: write
- uses: ./.github/workflows/api-docs.yml
- with:
- check_only: true
diff --git a/.github/workflows/api-docs.yml b/.github/workflows/api-docs.yml
index af0397c7cb..f083d32fce 100644
--- a/.github/workflows/api-docs.yml
+++ b/.github/workflows/api-docs.yml
@@ -1,23 +1,11 @@
-# Autogenerate the API docs on new commit to important branches
-# Also work as a check for PR's to not forget committing their doc changes
-# called from api-docs-check.yml
+# Check if any PR needs to run the autogenerate script
name: Autogenerate API docs
on:
- push:
+ pull_request:
paths:
- 'src/nvim/api/*.[ch]'
- 'runtime/lua/**.lua'
- 'runtime/doc/**'
- branches:
- - 'master'
- - 'release-[0-9]+.[0-9]+'
- workflow_dispatch:
- workflow_call:
- inputs:
- check_only:
- type: boolean
- default: false
- required: false
jobs:
regen-api-docs:
@@ -25,50 +13,26 @@ jobs:
permissions:
contents: write
pull-requests: write
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: rhysd/action-setup-vim@v1
with:
neovim: true
version: nightly
- uses: actions/checkout@v3
- with:
- # Fetch depth 0 is required if called through workflow_call. In order
- # to create a PR we need to access other branches, which requires a
- # full clone.
- fetch-depth: 0
-
- name: Install dependencies
run: |
sudo apt-get update
sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y doxygen python3 python3-msgpack
- - name: Set up git config
- run: |
- git config --global user.name 'marvim'
- git config --global user.email 'marvim@users.noreply.github.com'
-
- - run: printf 'DOC_BRANCH=marvim/api-doc-update/%s\n' ${GITHUB_REF#refs/heads/} >> $GITHUB_ENV
-
- name: Generate docs
id: docs
run: |
- git checkout -b ${DOC_BRANCH}
python3 scripts/gen_vimdoc.py
printf 'UPDATED_DOCS=%s\n' $([ -z "$(git diff)" ]; echo $?) >> $GITHUB_OUTPUT
- name: FAIL, PR has not committed doc changes
- if: ${{ steps.docs.outputs.UPDATED_DOCS != 0 && inputs.check_only }}
+ if: ${{ steps.docs.outputs.UPDATED_DOCS != 0 }}
run: |
echo "Job failed, run ./scripts/gen_vimdoc.py and commit your doc changes"
echo "The doc generation produces the following changes:"
git diff --color --exit-code
-
- - name: Automatic PR
- if: ${{ steps.docs.outputs.UPDATED_DOCS != 0 && !inputs.check_only }}
- run: |
- git add -u
- git commit -m 'docs: regenerate [skip ci]'
- git push --force https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY} ${DOC_BRANCH}
- gh pr create --draft --fill --base ${GITHUB_REF#refs/heads/} --head ${DOC_BRANCH} || true
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index be0f2f812c..26197cdcd3 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,5 +1,12 @@
name: build
on:
+ push:
+ paths:
+ - '**.cmake'
+ - '**/CMakeLists.txt'
+ - '**/CMakePresets.json'
+ - 'cmake.*/**'
+ - '.github/**'
pull_request:
branches:
- 'master'
@@ -12,7 +19,7 @@ on:
- '.github/**'
concurrency:
- group: ${{ github.workflow }}-${{ github.head_ref }}
+ group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.repository_owner == 'neovim' && github.sha || github.ref_name }}
cancel-in-progress: true
env:
@@ -71,3 +78,30 @@ jobs:
- name: Install
run: make install
+
+ use-existing-src:
+ name: Test USE_EXISTING_SRC_DIR=ON builds with no network access
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Install build dependencies
+ run: ./.github/scripts/install_deps.sh
+
+ - name: Build bundled dependencies
+ run: make deps
+
+ - name: Clean bundled dependencies à la neovim/deps
+ run: |
+ rm -rf ./build
+ find .deps .deps/build -maxdepth 1 '!' \( -name .deps -o -name build -o -name src \) -exec rm -r '{}' +
+ cd .deps/build/src
+ rm -rf ./*-build
+ rm -rf ./*-stamp/*-{configure,build,install,done}
+ for d in *; do (cd "$d"; rm -rf ./autom4te.cache; make clean || true; make distclean || true); done
+
+ - name: Re-build bundled dependencies with no network access
+ run: unshare --map-root-user --net make deps DEPS_CMAKE_FLAGS=-DUSE_EXISTING_SRC_DIR=ON
+
+ - name: Build
+ run: make CMAKE_FLAGS="-D CI_BUILD=ON"
diff --git a/.github/workflows/issue-open-check.yml b/.github/workflows/issue-open-check.yml
new file mode 100644
index 0000000000..2471670dc6
--- /dev/null
+++ b/.github/workflows/issue-open-check.yml
@@ -0,0 +1,34 @@
+name: Issue Open Check
+
+on:
+ issues:
+ types: [opened]
+
+jobs:
+ issue-open-check:
+ permissions:
+ issues: write
+ runs-on: ubuntu-latest
+ steps:
+ - name: check issue title
+ id: check-issue
+ uses: actions/github-script@v6
+ with:
+ script: |
+ const title = context.payload.issue.title;
+ const titleSplit = title.split(/\s+/).map(e => e.toLowerCase());
+ const keywords = ['api', 'treesitter', 'ui', 'lsp', 'doc'];
+ var match = new Set();
+ for(const keyword of keywords) {
+ if(titleSplit.includes(keyword)) {
+ match.add(keyword)
+ }
+ }
+ if(match.size !== 0){
+ github.rest.issues.addLabels({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.issue.number,
+ labels: Array.from(match)
+ })
+ }
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 5249b36f9a..e2027adc32 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -1,9 +1,6 @@
name: test
on:
push:
- branches:
- - 'master'
- - 'release-[0-9]+.[0-9]+'
pull_request:
branches:
- 'master'
@@ -12,25 +9,24 @@ on:
- 'contrib/**'
concurrency:
- group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
+ group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.repository_owner == 'neovim' && github.sha || github.ref_name }}
cancel-in-progress: true
env:
- ASAN_OPTIONS: detect_leaks=1:check_initialization_order=1:handle_abort=1:handle_sigill=1:log_path=${{ github.workspace }}/build/log/asan:intercept_tls_get_addr=0
+ ASAN_OPTIONS: detect_leaks=1:check_initialization_order=1:log_path=${{ github.workspace }}/build/log/asan:intercept_tls_get_addr=0
BIN_DIR: ${{ github.workspace }}/bin
BUILD_DIR: ${{ github.workspace }}/build
INSTALL_PREFIX: ${{ github.workspace }}/nvim-install
LOG_DIR: ${{ github.workspace }}/build/log
NVIM_LOG_FILE: ${{ github.workspace }}/build/.nvimlog
TSAN_OPTIONS: log_path=${{ github.workspace }}/build/log/tsan
- UBSAN_OPTIONS: "print_stacktrace=1 log_path=${{ github.workspace }}/build/log/ubsan"
+ UBSAN_OPTIONS: log_path=${{ github.workspace }}/build/log/ubsan
VALGRIND_LOG: ${{ github.workspace }}/build/log/valgrind-%p.log
# TEST_FILE: test/functional/core/startup_spec.lua
# TEST_FILTER: foo
jobs:
lint:
- if: (github.event_name == 'pull_request' && github.base_ref == 'master') || (github.event_name == 'push' && github.ref == 'refs/heads/master')
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
@@ -42,7 +38,7 @@ jobs:
- name: Install dependencies
run: |
./.github/scripts/install_deps.sh
- brew install stylua uncrustify
+ brew install stylua
- uses: ./.github/actions/cache
@@ -143,7 +139,7 @@ jobs:
- name: Install dependencies
run: ./.github/scripts/install_deps.sh --test
- - name: Setup interpreter packages
+ - name: Set up interpreter packages
run: |
# Use default CC to avoid compilation problems when installing Python modules.
echo "Install neovim module for Python."
@@ -183,16 +179,11 @@ jobs:
timeout-minutes: 5
run: cmake --build build --target unittest
- - if: matrix.flavor != 'functionaltest-lua' && (success() || failure() && steps.abort_job.outputs.status == 'success')
+ - if: success() || failure() && steps.abort_job.outputs.status == 'success'
name: Functionaltest
timeout-minutes: 20
run: cmake --build build --target functionaltest
- - if: matrix.flavor == 'functionaltest-lua' && (success() || failure() && steps.abort_job.outputs.status == 'success')
- name: Functionaltest with PUC Lua
- timeout-minutes: 20
- run: cmake --build build --target functionaltest-lua
-
- if: matrix.flavor != 'tsan' && (success() || failure() && steps.abort_job.outputs.status == 'success')
name: Oldtest
run: make oldtest
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 731bf09e2e..4e57d6905f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,18 +16,28 @@ project(nvim C)
if(POLICY CMP0075)
cmake_policy(SET CMP0075 NEW)
endif()
+if(POLICY CMP0135)
+ cmake_policy(SET CMP0135 NEW)
+endif()
# Point CMake at any custom modules we may ship
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
include(CheckCCompilerFlag)
include(CheckCSourceCompiles)
+include(CheckLibraryExists)
+include(ExternalProject)
include(FindPackageHandleStandardArgs)
+include(GNUInstallDirs)
+
+include(Deps)
include(InstallHelpers)
-include(LuaHelpers)
include(PreventInTreeBuilds)
include(Util)
+set_directory_properties(PROPERTIES
+ EP_PREFIX "${DEPS_BUILD_DIR}")
+
set(TOUCHES_DIR ${PROJECT_BINARY_DIR}/touches)
find_program(CCACHE_PRG ccache)
@@ -105,6 +115,12 @@ endif()
message(STATUS "CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}")
set_default_buildtype()
+get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(NOT isMultiConfig)
+ # Unlike build dependencies in cmake.deps, we assume we want dev dependencies
+ # such as Uncrustify to always be built with Release.
+ list(APPEND DEPS_CMAKE_ARGS -D CMAKE_BUILD_TYPE=Release)
+endif()
# If not in a git repo (e.g., a tarball) these tokens define the complete
# version string, else they are combined with the result of `git describe`.
@@ -216,19 +232,18 @@ endif()
#
# Lint
#
-find_program(LUACHECK_PRG luacheck)
find_program(SHELLCHECK_PRG shellcheck)
find_program(STYLUA_PRG stylua)
-find_program(UNCRUSTIFY_PRG uncrustify)
add_glob_target(
REQUIRED
TARGET lintlua-luacheck
- COMMAND ${LUACHECK_PRG}
+ COMMAND ${DEPS_BIN_DIR}/luacheck
FLAGS -q
GLOB_DIRS runtime/ scripts/ src/ test/
GLOB_PAT *.lua
TOUCH_STRATEGY SINGLE)
+add_dependencies(lintlua-luacheck luacheck)
add_glob_target(
TARGET lintlua-stylua
@@ -299,3 +314,14 @@ add_custom_target(uninstall
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(cmake.packaging)
endif()
+
+ExternalProject_Add(uncrustify
+ URL https://github.com/uncrustify/uncrustify/archive/uncrustify-0.77.1.tar.gz
+ URL_HASH SHA256=414bbc9f7860eb18a53074f9af14ed04638a633b2216a73f2629291300d37c1b
+ DOWNLOAD_NO_PROGRESS TRUE
+ DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/uncrustify
+ CMAKE_ARGS ${DEPS_CMAKE_ARGS}
+ CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS}
+ EXCLUDE_FROM_ALL TRUE)
+
+include(BuildLuarocks)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 85dc0fdbfd..4c8387fbd2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -187,7 +187,7 @@ master build. To view the defects, just request access; you will be approved.
```
- When running Neovim, use
```
- UBSAN_OPTIONS=print_stacktrace=1 ASAN_OPTIONS=log_path=/tmp/nvim_asan,handle_abort=1,handle_sigill=1 nvim args...
+ ASAN_OPTIONS=log_path=/tmp/nvim_asan nvim args...
```
- If Neovim exits unexpectedly, check `/tmp/nvim_asan.{PID}` (or your preferred `log_path`) for log files with error messages.
diff --git a/MAINTAIN.md b/MAINTAIN.md
index 91f09ee67e..2ba764851b 100644
--- a/MAINTAIN.md
+++ b/MAINTAIN.md
@@ -25,7 +25,7 @@ The forecasting problem might be solved with an explicit priority system (like
Bram's todo.txt). Meanwhile the Neovim priority system is defined by:
* PRs nearing completion.
-* Issue labels. E.g. the `+plan` label increases the ticket's priority merely
+* Issue labels. E.g. the `has:plan` label increases the ticket's priority merely
for having a plan written down: it is _closer to completion_ than tickets
without a plan.
* Comment activity or new information.
@@ -89,7 +89,7 @@ These dependencies are "vendored" (inlined), we must update the sources manually
* send improvements upstream!
* `src/xdiff/`: [xdiff](https://github.com/git/git/tree/master/xdiff)
* `src/cjson/`: [lua-cjson](https://github.com/openresty/lua-cjson)
-* `src/nvim/lib/`: [Klib](https://github.com/attractivechaos/klib)
+* `src/klib/`: [Klib](https://github.com/attractivechaos/klib)
* `runtime/lua/vim/inspect.lua`: [inspect.lua](https://github.com/kikito/inspect.lua)
* `src/nvim/tui/terminfo_defs.h`: terminfo definitions
* Run `scripts/update_terminfo.sh` to update these definitions.
diff --git a/Makefile b/Makefile
index cdf5f552ba..86416c92a7 100644
--- a/Makefile
+++ b/Makefile
@@ -126,7 +126,7 @@ test/old/testdir/%.vim: phony_force nvim
+$(SINGLE_MAKE) -C test/old/testdir NVIM_PRG=$(NVIM_PRG) SCRIPTS= $(MAKEOVERRIDES) $(patsubst test/old/testdir/%.vim,%,$@)
functionaltest-lua: | nvim
- $(BUILD_TOOL) -C build $@
+ $(BUILD_TOOL) -C build functionaltest
FORMAT=formatc formatlua format
LINT=lintlua lintsh lintc clang-tidy lintcommit lint
diff --git a/cmake.config/CMakeLists.txt b/cmake.config/CMakeLists.txt
index 6bf4a60cf1..26a7a262c1 100644
--- a/cmake.config/CMakeLists.txt
+++ b/cmake.config/CMakeLists.txt
@@ -158,7 +158,12 @@ configure_file (
"${PROJECT_BINARY_DIR}/cmake.config/auto/config.h"
)
-configure_file(versiondef.h.in auto/versiondef.h.gen)
+if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.15)
+ configure_file(versiondef.h.in auto/versiondef.h.gen)
+else()
+ configure_file(versiondef_old.h.in auto/versiondef.h.gen)
+endif()
+
file(GENERATE
OUTPUT "${PROJECT_BINARY_DIR}/cmake.config/auto/versiondef-$<CONFIG>.h"
INPUT "${PROJECT_BINARY_DIR}/cmake.config/auto/versiondef.h.gen")
diff --git a/cmake.config/iwyu/mapping.imp b/cmake.config/iwyu/mapping.imp
index 22710d8571..7cdd63a723 100644
--- a/cmake.config/iwyu/mapping.imp
+++ b/cmake.config/iwyu/mapping.imp
@@ -194,7 +194,6 @@
{ include: [ '"nvim/extmark_defs.h"', public, '"nvim/extmark.h"', public ] },
{ include: [ '"nvim/grid_defs.h"', public, '"nvim/grid.h"', public ] },
{ include: [ '"nvim/highlight_defs.h"', public, '"nvim/highlight.h"', public ] },
- { include: [ '"nvim/map_defs.h"', public, '"nvim/map.h"', public ] },
{ include: [ '"nvim/mark_defs.h"', public, '"nvim/mark.h"', public ] },
{ include: [ '"nvim/mbyte_defs.h"', public, '"nvim/mbyte.h"', public ] },
{ include: [ '"nvim/memfile_defs.h"', public, '"nvim/memfile.h"', public ] },
diff --git a/cmake.config/versiondef.h.in b/cmake.config/versiondef.h.in
index a4c0cfa2d9..b328c1fa00 100644
--- a/cmake.config/versiondef.h.in
+++ b/cmake.config/versiondef.h.in
@@ -15,7 +15,7 @@
#define NVIM_API_LEVEL_COMPAT @NVIM_API_LEVEL_COMPAT@
#define NVIM_API_PRERELEASE @NVIM_API_PRERELEASE@
-#define NVIM_VERSION_CFLAGS "${CMAKE_C_COMPILER} $<$<CONFIG:Debug>:${CMAKE_C_FLAGS_DEBUG}>$<$<CONFIG:Release>:${CMAKE_C_FLAGS_RELEASE}>$<$<CONFIG:RelWithDebInfo>:${CMAKE_C_FLAGS_RELWITHDEBINFO}>$<$<CONFIG:MinSizeRel>:${CMAKE_C_FLAGS_MINSIZEREL}> $<JOIN:$<TARGET_PROPERTY:nvim,COMPILE_OPTIONS>, > -D$<JOIN:$<TARGET_PROPERTY:nvim,COMPILE_DEFINITIONS>, -D> -I$<JOIN:$<TARGET_PROPERTY:nvim,INCLUDE_DIRECTORIES>, -I>"
+#define NVIM_VERSION_CFLAGS "${CMAKE_C_COMPILER} $<$<CONFIG:Debug>:${CMAKE_C_FLAGS_DEBUG}>$<$<CONFIG:Release>:${CMAKE_C_FLAGS_RELEASE}>$<$<CONFIG:RelWithDebInfo>:${CMAKE_C_FLAGS_RELWITHDEBINFO}>$<$<CONFIG:MinSizeRel>:${CMAKE_C_FLAGS_MINSIZEREL}> $<JOIN:$<TARGET_PROPERTY:nvim,COMPILE_OPTIONS>, > -D$<JOIN:$<TARGET_PROPERTY:nvim,COMPILE_DEFINITIONS>, -D> -I$<JOIN:$<REMOVE_DUPLICATES:$<TARGET_PROPERTY:nvim,INCLUDE_DIRECTORIES>>, -I>"
#define NVIM_VERSION_BUILD_TYPE "$<CONFIG>"
#endif // AUTO_VERSIONDEF_H
diff --git a/cmake.config/versiondef_old.h.in b/cmake.config/versiondef_old.h.in
new file mode 100644
index 0000000000..a4c0cfa2d9
--- /dev/null
+++ b/cmake.config/versiondef_old.h.in
@@ -0,0 +1,21 @@
+#ifndef AUTO_VERSIONDEF_H
+#define AUTO_VERSIONDEF_H
+
+#define NVIM_VERSION_MAJOR @NVIM_VERSION_MAJOR@
+#define NVIM_VERSION_MINOR @NVIM_VERSION_MINOR@
+#define NVIM_VERSION_PATCH @NVIM_VERSION_PATCH@
+#define NVIM_VERSION_PRERELEASE "@NVIM_VERSION_PRERELEASE@"
+
+#cmakedefine NVIM_VERSION_MEDIUM "@NVIM_VERSION_MEDIUM@"
+#ifndef NVIM_VERSION_MEDIUM
+# include "auto/versiondef_git.h"
+#endif
+
+#define NVIM_API_LEVEL @NVIM_API_LEVEL@
+#define NVIM_API_LEVEL_COMPAT @NVIM_API_LEVEL_COMPAT@
+#define NVIM_API_PRERELEASE @NVIM_API_PRERELEASE@
+
+#define NVIM_VERSION_CFLAGS "${CMAKE_C_COMPILER} $<$<CONFIG:Debug>:${CMAKE_C_FLAGS_DEBUG}>$<$<CONFIG:Release>:${CMAKE_C_FLAGS_RELEASE}>$<$<CONFIG:RelWithDebInfo>:${CMAKE_C_FLAGS_RELWITHDEBINFO}>$<$<CONFIG:MinSizeRel>:${CMAKE_C_FLAGS_MINSIZEREL}> $<JOIN:$<TARGET_PROPERTY:nvim,COMPILE_OPTIONS>, > -D$<JOIN:$<TARGET_PROPERTY:nvim,COMPILE_DEFINITIONS>, -D> -I$<JOIN:$<TARGET_PROPERTY:nvim,INCLUDE_DIRECTORIES>, -I>"
+#define NVIM_VERSION_BUILD_TYPE "$<CONFIG>"
+
+#endif // AUTO_VERSIONDEF_H
diff --git a/cmake.deps/CMakeLists.txt b/cmake.deps/CMakeLists.txt
index 3d835064ba..86d2228e68 100644
--- a/cmake.deps/CMakeLists.txt
+++ b/cmake.deps/CMakeLists.txt
@@ -9,21 +9,13 @@ endif()
# Point CMake at any custom modules we may ship
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" "${PROJECT_SOURCE_DIR}/../cmake")
+include(ExternalProject)
include(CheckCCompilerFlag)
-include(Util)
-
-set(DEPS_CMAKE_ARGS
- -D CMAKE_C_COMPILER=${CMAKE_C_COMPILER}
- -D CMAKE_C_STANDARD=99
- -D CMAKE_GENERATOR=${CMAKE_GENERATOR}
- -D CMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
- -D CMAKE_POSITION_INDEPENDENT_CODE=ON
- -D CMAKE_FIND_FRAMEWORK=${CMAKE_FIND_FRAMEWORK})
-set(DEPS_CMAKE_CACHE_ARGS -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES})
+include(Deps)
+include(Util)
set_default_buildtype()
-
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(NOT isMultiConfig)
list(APPEND DEPS_CMAKE_ARGS -D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})
@@ -36,15 +28,8 @@ if(HAS_OG_FLAG)
set(DEFAULT_MAKE_CFLAGS CFLAGS+=-Og ${DEFAULT_MAKE_CFLAGS})
endif()
-set(DEPS_INSTALL_DIR "${CMAKE_BINARY_DIR}/usr")
-set(DEPS_BIN_DIR "${DEPS_INSTALL_DIR}/bin")
-set(DEPS_LIB_DIR "${DEPS_INSTALL_DIR}/lib")
-set(DEPS_BUILD_DIR "${CMAKE_BINARY_DIR}/build")
-set(DEPS_DOWNLOAD_DIR "${DEPS_BUILD_DIR}/downloads")
set(DEPS_INCLUDE_FLAGS "-I${DEPS_INSTALL_DIR}/include -I${DEPS_INSTALL_DIR}/include/luajit-2.1")
-list(APPEND DEPS_CMAKE_ARGS -D CMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR})
-
option(USE_BUNDLED "Use bundled dependencies." ON)
option(USE_BUNDLED_UNIBILIUM "Use the bundled unibilium." ${USE_BUNDLED})
@@ -53,7 +38,6 @@ option(USE_BUNDLED_LIBVTERM "Use the bundled libvterm." ${USE_BUNDLED})
option(USE_BUNDLED_LIBUV "Use the bundled libuv." ${USE_BUNDLED})
option(USE_BUNDLED_MSGPACK "Use the bundled msgpack." ${USE_BUNDLED})
option(USE_BUNDLED_LUAJIT "Use the bundled version of luajit." ${USE_BUNDLED})
-option(USE_BUNDLED_LUAROCKS "Use the bundled version of luarocks." ${USE_BUNDLED})
option(USE_BUNDLED_LUV "Use the bundled version of luv." ${USE_BUNDLED})
option(USE_BUNDLED_LPEG "Use the bundled lpeg." ${USE_BUNDLED})
#XXX(tarruda): Lua is only used for debugging the functional test client, don't
@@ -81,45 +65,6 @@ if(NOT Git_FOUND)
message(FATAL_ERROR "Git is required to apply patches.")
endif()
-if(UNIX)
- find_program(MAKE_PRG NAMES gmake make)
- if(NOT MAKE_PRG)
- message(FATAL_ERROR "GNU Make is required to build the dependencies.")
- else()
- message(STATUS "Found GNU Make at ${MAKE_PRG}")
- endif()
-endif()
-
-# When using make, use the $(MAKE) variable to avoid warning about the job
-# server.
-if(CMAKE_GENERATOR MATCHES "Makefiles")
- set(MAKE_PRG "$(MAKE)")
-endif()
-
-if(MINGW AND CMAKE_GENERATOR MATCHES "Ninja")
- find_program(MAKE_PRG NAMES mingw32-make)
- if(NOT MAKE_PRG)
- message(FATAL_ERROR "GNU Make for mingw32 is required to build the dependencies.")
- else()
- message(STATUS "Found GNU Make for mingw32: ${MAKE_PRG}")
- endif()
-endif()
-
-set(DEPS_C_COMPILER "${CMAKE_C_COMPILER}")
-
-if(CMAKE_OSX_SYSROOT)
- set(DEPS_C_COMPILER "${DEPS_C_COMPILER} -isysroot${CMAKE_OSX_SYSROOT}")
-endif()
-
-if(CMAKE_OSX_ARCHITECTURES)
- # The LuaJIT build does not like being passed multiple `-arch` flags
- # so we handle a universal build the old-fashioned way.
- set(LUAJIT_C_COMPILER "${DEPS_C_COMPILER}")
- foreach(ARCH IN LISTS CMAKE_OSX_ARCHITECTURES)
- set(DEPS_C_COMPILER "${DEPS_C_COMPILER} -arch ${ARCH}")
- endforeach()
-endif()
-
# If the macOS deployment target is not set manually (via $MACOSX_DEPLOYMENT_TARGET),
# fall back to local system version. Needs to be done here and in top-level CMakeLists.txt.
if(APPLE)
@@ -132,8 +77,9 @@ if(APPLE)
message(STATUS "Using deployment target ${CMAKE_OSX_DEPLOYMENT_TARGET}")
endif()
-include(ExternalProject)
-set_directory_properties(PROPERTIES EP_PREFIX "${DEPS_BUILD_DIR}")
+set_directory_properties(PROPERTIES
+ EP_PREFIX "${DEPS_BUILD_DIR}"
+ CMAKE_CONFIGURE_DEPENDS deps.txt)
file(READ deps.txt DEPENDENCIES)
STRING(REGEX REPLACE "\n" ";" DEPENDENCIES "${DEPENDENCIES}")
@@ -141,16 +87,13 @@ foreach(dep ${DEPENDENCIES})
STRING(REGEX REPLACE " " ";" dep "${dep}")
list(GET dep 0 name)
list(GET dep 1 value)
-
- if(name MATCHES "^.*URL$")
- mark_as_advanced(${name})
+ if(NOT ${name})
+ # _URL variables must NOT be set when USE_EXISTING_SRC_DIR is set,
+ # otherwise ExternalProject will try to re-download the sources.
if(NOT USE_EXISTING_SRC_DIR)
- set(${name} ${value} CACHE STRING "")
+ set(${name} ${value})
endif()
- elseif(name MATCHES "^.*SHA256$")
- set(${name} ${value})
endif()
-
endforeach()
if(USE_BUNDLED_UNIBILIUM)
@@ -184,10 +127,6 @@ if(USE_BUNDLED_LUA)
include(BuildLua)
endif()
-if(USE_BUNDLED_LUAROCKS)
- include(BuildLuarocks)
-endif()
-
if(USE_BUNDLED_LUV)
include(BuildLuv)
endif()
diff --git a/cmake.deps/cmake/BuildLua.cmake b/cmake.deps/cmake/BuildLua.cmake
index 3e7b5dee51..24da331867 100644
--- a/cmake.deps/cmake/BuildLua.cmake
+++ b/cmake.deps/cmake/BuildLua.cmake
@@ -51,12 +51,3 @@ ExternalProject_Add(lua
BUILD_IN_SOURCE 1
BUILD_COMMAND ${MAKE_PRG} ${LUA_INSTALL_TOP_ARG} ${LUA_TARGET}
INSTALL_COMMAND ${MAKE_PRG} ${LUA_INSTALL_TOP_ARG} install)
-
-set(BUSTED ${DEPS_BIN_DIR}/busted)
-set(BUSTED_LUA ${BUSTED}-lua)
-
-add_custom_command(OUTPUT ${BUSTED_LUA}
- COMMAND sed -e 's/^exec/exec $$LUA_DEBUGGER/' -e 's/jit//g' < ${BUSTED} > ${BUSTED_LUA} && chmod +x ${BUSTED_LUA}
- DEPENDS lua busted ${BUSTED})
-add_custom_target(busted-lua ALL
- DEPENDS ${DEPS_BIN_DIR}/busted-lua)
diff --git a/cmake.deps/cmake/BuildLuajit.cmake b/cmake.deps/cmake/BuildLuajit.cmake
index 04696baf9b..554add1c4a 100644
--- a/cmake.deps/cmake/BuildLuajit.cmake
+++ b/cmake.deps/cmake/BuildLuajit.cmake
@@ -66,6 +66,11 @@ if((UNIX AND NOT APPLE) OR (APPLE AND NOT CMAKE_OSX_ARCHITECTURES))
elseif(CMAKE_OSX_ARCHITECTURES AND APPLE)
+ set(LUAJIT_C_COMPILER "${CMAKE_C_COMPILER}")
+ if(CMAKE_OSX_SYSROOT)
+ set(LUAJIT_C_COMPILER "${LUAJIT_C_COMPILER} -isysroot${CMAKE_OSX_SYSROOT}")
+ endif()
+
# Passing multiple `-arch` flags to the LuaJIT build will cause it to fail.
# To get a working universal build, we build each requested architecture slice
# individually then `lipo` them all up.
@@ -122,8 +127,7 @@ elseif(MINGW)
COMMAND ${CMAKE_COMMAND} -E copy ${DEPS_BUILD_DIR}/src/luajit/src/libluajit.a ${DEPS_LIB_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_INSTALL_DIR}/include/luajit-2.1
COMMAND ${CMAKE_COMMAND} -DFROM_GLOB=${DEPS_BUILD_DIR}/src/luajit/src/*.h -DTO=${DEPS_INSTALL_DIR}/include/luajit-2.1 -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CopyFilesGlob.cmake
- COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_BIN_DIR}/lua/jit
- COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEPS_BUILD_DIR}/src/luajit/src/jit ${DEPS_BIN_DIR}/lua/jit
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEPS_BUILD_DIR}/src/luajit/src/jit ${DEPS_INSTALL_DIR}/share/luajit-2.1.0-beta3/jit
)
elseif(MSVC)
@@ -139,8 +143,7 @@ elseif(MSVC)
COMMAND ${CMAKE_COMMAND} -E copy ${DEPS_BUILD_DIR}/src/luajit/src/lua51.lib ${DEPS_LIB_DIR}/luajit.lib
COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_INSTALL_DIR}/include/luajit-2.1
COMMAND ${CMAKE_COMMAND} -DFROM_GLOB=${DEPS_BUILD_DIR}/src/luajit/src/*.h -DTO=${DEPS_INSTALL_DIR}/include/luajit-2.1 -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CopyFilesGlob.cmake
- COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_BIN_DIR}/lua/jit
- COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEPS_BUILD_DIR}/src/luajit/src/jit ${DEPS_BIN_DIR}/lua/jit
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEPS_BUILD_DIR}/src/luajit/src/jit ${DEPS_INSTALL_DIR}/share/luajit-2.1.0-beta3/jit
)
else()
message(FATAL_ERROR "Trying to build luajit in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}")
diff --git a/cmake.deps/cmake/BuildLuarocks.cmake b/cmake.deps/cmake/BuildLuarocks.cmake
deleted file mode 100644
index cb29ed9d95..0000000000
--- a/cmake.deps/cmake/BuildLuarocks.cmake
+++ /dev/null
@@ -1,137 +0,0 @@
-# Luarocks recipe. Luarocks is only required when building Neovim.
-# NOTE: LuaRocks rocks need to "DEPENDS" on the previous module, because
-# running luarocks in parallel will break, e.g. when some rocks have
-# the same dependency.
-
-option(USE_BUNDLED_BUSTED "Use the bundled version of busted to run tests." ON)
-
-# The luarocks binary location
-set(LUAROCKS_BINARY ${DEPS_BIN_DIR}/luarocks)
-
-# Arguments for calls to 'luarocks build'
-if(NOT MSVC)
- # In MSVC don't pass the compiler/linker to luarocks, the bundled
- # version already knows, and passing them here breaks the build
- set(LUAROCKS_BUILDARGS CC=${DEPS_C_COMPILER} LD=${DEPS_C_COMPILER})
-endif()
-
-# Lua version, used with rocks directories.
-# Defaults to 5.1 for bundled LuaJIT/Lua.
-set(LUA_VERSION "5.1")
-
-if(UNIX)
-
- if(USE_BUNDLED_LUAJIT)
- list(APPEND LUAROCKS_OPTS
- --with-lua=${DEPS_INSTALL_DIR}
- --with-lua-include=${DEPS_INSTALL_DIR}/include/luajit-2.1
- --with-lua-interpreter=luajit)
- elseif(USE_BUNDLED_LUA)
- list(APPEND LUAROCKS_OPTS
- --with-lua=${DEPS_INSTALL_DIR})
- else()
- find_package(Luajit)
- if(LUAJIT_FOUND)
- list(APPEND LUAROCKS_OPTS
- --with-lua-include=${LUAJIT_INCLUDE_DIRS}
- --with-lua-interpreter=luajit)
- endif()
-
- # Get LUA_VERSION used with rocks output.
- if(LUAJIT_FOUND)
- set(LUA_EXE "luajit")
- else()
- set(LUA_EXE "lua")
- endif()
- execute_process(
- COMMAND ${LUA_EXE} -e "print(string.sub(_VERSION, 5))"
- OUTPUT_VARIABLE LUA_VERSION
- ERROR_VARIABLE ERR
- RESULT_VARIABLE RES)
- if(NOT RES EQUAL 0)
- message(FATAL_ERROR "Could not get LUA_VERSION with ${LUA_EXE}: ${ERR}")
- endif()
- endif()
-
- set(LUAROCKS_CONFIGURE_COMMAND ${DEPS_BUILD_DIR}/src/luarocks/configure
- --prefix=${DEPS_INSTALL_DIR} --force-config ${LUAROCKS_OPTS})
- set(LUAROCKS_INSTALL_COMMAND ${MAKE_PRG} -j1 bootstrap)
-elseif(MSVC OR MINGW)
-
- if(MINGW)
- set(COMPILER_FLAG /MW)
- elseif(MSVC)
- set(COMPILER_FLAG /MSVC)
- endif()
-
- # Ignore USE_BUNDLED_LUAJIT - always ON for native Win32
- set(LUAROCKS_INSTALL_COMMAND install.bat /FORCECONFIG /NOREG /NOADMIN /Q /F
- /LUA ${DEPS_INSTALL_DIR}
- /LIB ${DEPS_LIB_DIR}
- /BIN ${DEPS_BIN_DIR}
- /INC ${DEPS_INSTALL_DIR}/include/luajit-2.1
- /P ${DEPS_INSTALL_DIR}/luarocks /TREE ${DEPS_INSTALL_DIR}
- /SCRIPTS ${DEPS_BIN_DIR}
- /CMOD ${DEPS_BIN_DIR}
- ${COMPILER_FLAG}
- /LUAMOD ${DEPS_BIN_DIR}/lua)
-
- set(LUAROCKS_BINARY ${DEPS_INSTALL_DIR}/luarocks/luarocks.bat)
-else()
- message(FATAL_ERROR "Trying to build luarocks in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}")
-endif()
-
-ExternalProject_Add(luarocks
- URL ${LUAROCKS_URL}
- URL_HASH SHA256=${LUAROCKS_SHA256}
- DOWNLOAD_NO_PROGRESS TRUE
- DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/luarocks
- BUILD_IN_SOURCE 1
- CONFIGURE_COMMAND "${LUAROCKS_CONFIGURE_COMMAND}"
- BUILD_COMMAND ""
- INSTALL_COMMAND "${LUAROCKS_INSTALL_COMMAND}")
-
-if(USE_BUNDLED_LUAJIT)
- add_dependencies(luarocks luajit)
-elseif(USE_BUNDLED_LUA)
- add_dependencies(luarocks lua)
-endif()
-set(ROCKS_DIR ${DEPS_LIB_DIR}/luarocks/rocks-${LUA_VERSION})
-
-if(MSVC)
- # Workaround for luarocks failing to find the md5sum.exe it is shipped with.
- list(APPEND LUAROCKS_BUILDARGS MD5SUM=md5sum)
- set(PATH PATH=${DEPS_INSTALL_DIR}/luarocks/tools;$ENV{PATH})
-endif()
-
-set(CURRENT_DEP luarocks)
-
-function(Download ROCK VER)
- if(ARGV2)
- set(OUTPUT ${ARGV2})
- else()
- set(OUTPUT ${ROCKS_DIR}/${ROCK})
- endif()
- add_custom_command(OUTPUT ${OUTPUT}
- COMMAND ${CMAKE_COMMAND} -E env "${PATH}" ${LUAROCKS_BINARY} build ${ROCK} ${VER} ${LUAROCKS_BUILDARGS}
- DEPENDS ${CURRENT_DEP})
- add_custom_target(${ROCK} ALL DEPENDS ${OUTPUT})
- set(CURRENT_DEP ${ROCK} PARENT_SCOPE)
-endfunction()
-
-if(USE_BUNDLED_BUSTED)
- if(WIN32)
- set(BUSTED_EXE "${DEPS_BIN_DIR}/busted.bat")
- set(LUACHECK_EXE "${DEPS_BIN_DIR}/luacheck.bat")
- else()
- set(BUSTED_EXE "${DEPS_BIN_DIR}/busted")
- set(LUACHECK_EXE "${DEPS_BIN_DIR}/luacheck")
- endif()
-
- Download(busted 2.1.1 ${BUSTED_EXE})
- Download(luacheck 1.1.0-1 ${LUACHECK_EXE})
-
- if (USE_BUNDLED_LUA OR NOT USE_BUNDLED_LUAJIT)
- Download(coxpcall 1.17.0-1)
- endif()
-endif()
diff --git a/cmake.deps/cmake/BuildLuv.cmake b/cmake.deps/cmake/BuildLuv.cmake
index 08168c9804..7220333de1 100644
--- a/cmake.deps/cmake/BuildLuv.cmake
+++ b/cmake.deps/cmake/BuildLuv.cmake
@@ -2,7 +2,6 @@ set(LUV_CMAKE_ARGS
-D LUA_BUILD_TYPE=System
-D LUA_COMPAT53_DIR=${DEPS_BUILD_DIR}/src/lua-compat-5.3
-D WITH_SHARED_LIBUV=ON
- -D BUILD_SHARED_LIBS=OFF
-D BUILD_STATIC_LIBS=ON
-D BUILD_MODULE=OFF)
@@ -38,7 +37,7 @@ ExternalProject_Add(lua-compat-5.3
BUILD_COMMAND ""
INSTALL_COMMAND "")
-ExternalProject_Add(luv-static
+ExternalProject_Add(luv
DEPENDS lua-compat-5.3
URL ${LUV_URL}
URL_HASH SHA256=${LUV_SHA256}
@@ -49,10 +48,10 @@ ExternalProject_Add(luv-static
CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS})
if(USE_BUNDLED_LUAJIT)
- add_dependencies(luv-static luajit)
+ add_dependencies(luv luajit)
elseif(USE_BUNDLED_LUA)
- add_dependencies(luv-static lua)
+ add_dependencies(luv lua)
endif()
if(USE_BUNDLED_LIBUV)
- add_dependencies(luv-static libuv)
+ add_dependencies(luv libuv)
endif()
diff --git a/cmake.deps/cmake/BuildMsgpack.cmake b/cmake.deps/cmake/BuildMsgpack.cmake
index c9033be1ae..f63559e6b4 100644
--- a/cmake.deps/cmake/BuildMsgpack.cmake
+++ b/cmake.deps/cmake/BuildMsgpack.cmake
@@ -7,11 +7,3 @@ ExternalProject_Add(msgpack
-D MSGPACK_BUILD_TESTS=OFF
-D MSGPACK_BUILD_EXAMPLES=OFF
CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS})
-
-if (NOT MSVC)
- add_custom_target(clean_shared_libraries_msgpack ALL
- COMMAND ${CMAKE_COMMAND}
- -D REMOVE_FILE_GLOB=${DEPS_LIB_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}*${CMAKE_SHARED_LIBRARY_SUFFIX}*
- -P ${PROJECT_SOURCE_DIR}/cmake/RemoveFiles.cmake)
- add_dependencies(clean_shared_libraries_msgpack msgpack)
-endif()
diff --git a/cmake.deps/cmake/CopyFilesGlob.cmake b/cmake.deps/cmake/CopyFilesGlob.cmake
index 8950ead1e5..7d0f4fc289 100644
--- a/cmake.deps/cmake/CopyFilesGlob.cmake
+++ b/cmake.deps/cmake/CopyFilesGlob.cmake
@@ -14,7 +14,7 @@ execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${TO})
file(GLOB files ${FROM_GLOB})
foreach(file ${files})
execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${file} ${TO} RESULT_VARIABLE rv)
- if(NOT rv EQUAL 0)
+ if(rv)
message(FATAL_ERROR "Error copying ${file}")
endif()
endforeach()
diff --git a/cmake.deps/deps.txt b/cmake.deps/deps.txt
index cd687cf929..1a720bc1f3 100644
--- a/cmake.deps/deps.txt
+++ b/cmake.deps/deps.txt
@@ -1,5 +1,5 @@
-LIBUV_URL https://github.com/libuv/libuv/archive/62c2374a8c005ce9e42088965f8f8af2532c177b.tar.gz
-LIBUV_SHA256 c7e89137da65a1cb550ba96b892dfeeabea982bf33b9237bcf9bbcd90f2e70a1
+LIBUV_URL https://github.com/libuv/libuv/archive/v1.45.0.tar.gz
+LIBUV_SHA256 458e34d5ef7f3c0394a2bfd8c39d757cb1553baa5959b9b4b45df63aa027a228
MSGPACK_URL https://github.com/msgpack/msgpack-c/releases/download/c-6.0.0/msgpack-c-6.0.0.tar.gz
MSGPACK_SHA256 3654f5e2c652dc52e0a993e270bb57d5702b262703f03771c152bba51602aeba
@@ -10,20 +10,17 @@ LUAJIT_SHA256 a9bcd9e646e2b188e1d7e3fb594e04c61dda3b332dfd0378d41be19c1eae9d09
LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz
LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333
-LUAROCKS_URL https://github.com/luarocks/luarocks/archive/v3.9.2.tar.gz
-LUAROCKS_SHA256 a0b36cd68586cd79966d0106bb2e5a4f5523327867995fd66bee4237062b3e3b
-
UNIBILIUM_URL https://github.com/neovim/unibilium/archive/d72c3598e7ac5d1ebf86ee268b8b4ed95c0fa628.tar.gz
UNIBILIUM_SHA256 9c4747c862ab5e3076dcf8fa8f0ea7a6b50f20ec5905618b9536655596797487
LIBTERMKEY_URL https://github.com/neovim/deps/raw/aa004f1b2b6470a92363cba8e1cc1874141dacc4/opt/libtermkey-0.22.tar.gz
LIBTERMKEY_SHA256 6945bd3c4aaa83da83d80a045c5563da4edd7d0374c62c0d35aec09eb3014600
-LIBVTERM_URL https://github.com/neovim/deps/raw/aa004f1b2b6470a92363cba8e1cc1874141dacc4/opt/libvterm-0.3.1.tar.gz
-LIBVTERM_SHA256 25a8ad9c15485368dfd0a8a9dca1aec8fea5c27da3fa74ec518d5d3787f0c397
+LIBVTERM_URL https://github.com/neovim/deps/raw/6c0a5213d062f2210fd5fecb9524ac27ca018ef4/opt/libvterm-0.3.2.tar.gz
+LIBVTERM_SHA256 91eb5088069f4e6edab69e14c4212f6da0192e65695956dc048016a0dab8bcf6
-LUV_URL https://github.com/luvit/luv/archive/093a977b82077591baefe1e880d37dfa2730bd54.tar.gz
-LUV_SHA256 222b38b6425f0926218e14e7da81481fdde6f9660c1feac25a53e6fb52e886e6
+LUV_URL https://github.com/luvit/luv/archive/c1497c0ffd3e1400a137ac99a614159a685f716b.tar.gz
+LUV_SHA256 fc8c8c777454b78e09c06bd177860da9b79804affc967b015ecccb75b3af6893
LPEG_URL https://github.com/neovim/deps/raw/aa004f1b2b6470a92363cba8e1cc1874141dacc4/opt/lpeg-1.0.2.tar.gz
LPEG_SHA256 48d66576051b6c78388faad09b70493093264588fcd0f258ddaab1cdd4a15ffe
@@ -52,13 +49,13 @@ LIBICONV_SHA256 ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178
TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.20.2.tar.gz
TREESITTER_C_SHA256 af66fde03feb0df4faf03750102a0d265b007e5d957057b6b293c13116a70af2
-TREESITTER_LUA_URL https://github.com/MunifTanjim/tree-sitter-lua/archive/v0.0.14.tar.gz
-TREESITTER_LUA_SHA256 930d0370dc15b66389869355c8e14305b9ba7aafd36edbfdb468c8023395016d
+TREESITTER_LUA_URL https://github.com/MunifTanjim/tree-sitter-lua/archive/v0.0.17.tar.gz
+TREESITTER_LUA_SHA256 8963fd0a185d786c164dfca3824941c7eaec497ce49a3a0bc24bf753f5e0e59c
TREESITTER_VIM_URL https://github.com/neovim/tree-sitter-vim/archive/v0.3.0.tar.gz
TREESITTER_VIM_SHA256 403acec3efb7cdb18ff3d68640fc823502a4ffcdfbb71cec3f98aa786c21cbe2
TREESITTER_VIMDOC_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v2.0.0.tar.gz
TREESITTER_VIMDOC_SHA256 1ff8f4afd3a9599dd4c3ce87c155660b078c1229704d1a254433e33794b8f274
TREESITTER_QUERY_URL https://github.com/nvim-treesitter/tree-sitter-query/archive/v0.1.0.tar.gz
TREESITTER_QUERY_SHA256 e2b806f80e8bf1c4f4e5a96248393fe6622fc1fc6189d6896d269658f67f914c
-TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/321a652626c63bfea3ea320083a4b14863b80270.tar.gz
-TREESITTER_SHA256 8f780289d9524a680e548d891c07dab025241fffdea86f8b55921e4024a84757
+TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/91e4d940169a0c0b024560632ef53c4f119117ca.tar.gz
+TREESITTER_SHA256 e15e335d127d38aaa73e727f3169df6015f43de1010d806e69b9e9222ad50fe1
diff --git a/cmake.packaging/CMakeLists.txt b/cmake.packaging/CMakeLists.txt
index c693e2f9ac..cf7196fd6e 100644
--- a/cmake.packaging/CMakeLists.txt
+++ b/cmake.packaging/CMakeLists.txt
@@ -40,8 +40,7 @@ if(WIN32)
set(CPACK_PACKAGE_EXECUTABLES "nvim" "Neovim" "nvim-qt" "Neovim Qt")
set(CPACK_CREATE_DESKTOP_LINKS "nvim-qt")
- # We use a wix patch to add further options to the installer. At present, it just adds neovim to the path
- # on installation and defines per-user installation, however, it can be extended.
+ # We use a wix patch to add further options to the installer.
# See: https://cmake.org/cmake/help/v3.7/module/CPackWIX.html#variable:CPACK_WIX_PATCH_FILE
list(APPEND CPACK_WIX_EXTENSIONS WixUtilExtension)
list(APPEND CPACK_WIX_PATCH_FILE ${CMAKE_CURRENT_LIST_DIR}/WixPatch.xml)
diff --git a/cmake/BuildLuarocks.cmake b/cmake/BuildLuarocks.cmake
new file mode 100644
index 0000000000..c5e08d2d74
--- /dev/null
+++ b/cmake/BuildLuarocks.cmake
@@ -0,0 +1,109 @@
+# Luarocks recipe. Luarocks is only required when testing Neovim.
+# NOTE: LuaRocks rocks need to "DEPENDS" on the previous module, because
+# running luarocks in parallel will break, e.g. when some rocks have
+# the same dependency.
+
+# The luarocks binary location
+set(LUAROCKS_BINARY ${DEPS_BIN_DIR}/luarocks)
+
+# Arguments for calls to 'luarocks build'
+if(NOT MSVC)
+ # In MSVC don't pass the compiler/linker to luarocks, the bundled
+ # version already knows, and passing them here breaks the build
+ set(LUAROCKS_BUILDARGS CC=${DEPS_C_COMPILER} LD=${DEPS_C_COMPILER})
+endif()
+
+if(UNIX)
+ if(PREFER_LUA)
+ find_package(Lua 5.1 EXACT REQUIRED)
+ get_filename_component(LUA_ROOT ${LUA_INCLUDE_DIR} DIRECTORY)
+ list(APPEND LUAROCKS_OPTS
+ --with-lua=${LUA_ROOT})
+ else()
+ find_package(Luajit REQUIRED)
+ get_filename_component(LUA_ROOT ${LUAJIT_INCLUDE_DIR} DIRECTORY)
+ get_filename_component(LUA_ROOT ${LUA_ROOT} DIRECTORY)
+ list(APPEND LUAROCKS_OPTS
+ --with-lua=${LUA_ROOT}
+ --with-lua-include=${LUAJIT_INCLUDE_DIR}
+ --with-lua-interpreter=luajit)
+ endif()
+
+ set(LUAROCKS_CONFIGURE_COMMAND ${DEPS_BUILD_DIR}/src/luarocks/configure
+ --prefix=${DEPS_INSTALL_DIR} --force-config ${LUAROCKS_OPTS})
+ set(LUAROCKS_INSTALL_COMMAND ${MAKE_PRG} -j1 bootstrap)
+elseif(MSVC OR MINGW)
+ if(MINGW)
+ set(COMPILER_FLAG /MW)
+ elseif(MSVC)
+ set(COMPILER_FLAG /MSVC)
+ endif()
+
+ find_package(Luajit REQUIRED)
+ # Always assume bundled luajit for native Win32
+ set(LUAROCKS_INSTALL_COMMAND install.bat /FORCECONFIG /NOREG /NOADMIN /Q /F
+ /LUA ${DEPS_PREFIX}
+ /INC ${LUAJIT_INCLUDE_DIR}
+ /P ${DEPS_INSTALL_DIR}/luarocks
+ /TREE ${DEPS_INSTALL_DIR}
+ /SCRIPTS ${DEPS_BIN_DIR}
+ ${COMPILER_FLAG})
+
+ set(LUAROCKS_BINARY ${DEPS_INSTALL_DIR}/luarocks/luarocks.bat)
+else()
+ message(FATAL_ERROR "Trying to build luarocks in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}")
+endif()
+
+ExternalProject_Add(luarocks
+ URL https://github.com/luarocks/luarocks/archive/v3.9.2.tar.gz
+ URL_HASH SHA256=a0b36cd68586cd79966d0106bb2e5a4f5523327867995fd66bee4237062b3e3b
+ DOWNLOAD_NO_PROGRESS TRUE
+ DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/luarocks
+ BUILD_IN_SOURCE 1
+ CONFIGURE_COMMAND "${LUAROCKS_CONFIGURE_COMMAND}"
+ BUILD_COMMAND ""
+ INSTALL_COMMAND "${LUAROCKS_INSTALL_COMMAND}"
+ EXCLUDE_FROM_ALL TRUE)
+
+set(ROCKS_DIR ${DEPS_LIB_DIR}/luarocks/rocks)
+
+if(MSVC)
+ # Workaround for luarocks failing to find the md5sum.exe it is shipped with.
+ list(APPEND LUAROCKS_BUILDARGS MD5SUM=md5sum)
+ set(PATH PATH=${DEPS_INSTALL_DIR}/luarocks/tools;$ENV{PATH})
+endif()
+
+set(CURRENT_DEP luarocks)
+
+function(Download ROCK VER)
+ if(ARGV2)
+ set(OUTPUT ${ARGV2})
+ else()
+ set(OUTPUT ${ROCKS_DIR}/${ROCK})
+ endif()
+ add_custom_command(OUTPUT ${OUTPUT}
+ COMMAND ${CMAKE_COMMAND} -E env "${PATH}" ${LUAROCKS_BINARY} build ${ROCK} ${VER} ${LUAROCKS_BUILDARGS}
+ DEPENDS ${CURRENT_DEP})
+ add_custom_target(${ROCK} DEPENDS ${OUTPUT})
+ set(CURRENT_DEP ${ROCK} PARENT_SCOPE)
+endfunction()
+
+if(WIN32)
+ set(BUSTED_EXE "${DEPS_BIN_DIR}/busted.bat")
+ set(LUACHECK_EXE "${DEPS_BIN_DIR}/luacheck.bat")
+else()
+ set(BUSTED_EXE "${DEPS_BIN_DIR}/busted")
+ set(LUACHECK_EXE "${DEPS_BIN_DIR}/luacheck")
+endif()
+
+add_custom_target(test_deps)
+
+Download(luacheck 1.1.0-1 ${LUACHECK_EXE})
+
+Download(busted 2.1.1 ${BUSTED_EXE})
+add_dependencies(test_deps busted)
+
+if(PREFER_LUA)
+ Download(coxpcall 1.17.0-1)
+ add_dependencies(test_deps coxpcall)
+endif()
diff --git a/cmake/CheckUncrustifyVersion.cmake b/cmake/CheckUncrustifyVersion.cmake
deleted file mode 100644
index 4812c24ace..0000000000
--- a/cmake/CheckUncrustifyVersion.cmake
+++ /dev/null
@@ -1,13 +0,0 @@
-if(UNCRUSTIFY_PRG)
- execute_process(COMMAND uncrustify --version
- OUTPUT_VARIABLE user_version
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- string(REGEX REPLACE "[A-Za-z_#-]" "" user_version ${user_version})
-
- file(STRINGS ${CONFIG_FILE} required_version LIMIT_COUNT 1)
- string(REGEX REPLACE "[A-Za-z_# -]" "" required_version ${required_version})
-
- if(NOT user_version STREQUAL required_version)
- message(FATAL_ERROR "Wrong uncrustify version! Required version is ${required_version} but found ${user_version}")
- endif()
-endif()
diff --git a/cmake/ConvertPo.cmake b/cmake/ConvertPo.cmake
index 2282b96f56..202cd3fbb3 100644
--- a/cmake/ConvertPo.cmake
+++ b/cmake/ConvertPo.cmake
@@ -6,7 +6,7 @@ execute_process(
OUTPUT_VARIABLE trans
ERROR_VARIABLE err
RESULT_VARIABLE res)
-if(NOT res EQUAL 0)
+if(res)
message(FATAL_ERROR "iconv failed to run correctly: ${err}")
endif()
diff --git a/cmake/Deps.cmake b/cmake/Deps.cmake
new file mode 100644
index 0000000000..69a950eb0d
--- /dev/null
+++ b/cmake/Deps.cmake
@@ -0,0 +1,54 @@
+set(DEPS_INSTALL_DIR "${CMAKE_BINARY_DIR}/usr")
+set(DEPS_BIN_DIR "${DEPS_INSTALL_DIR}/bin")
+set(DEPS_LIB_DIR "${DEPS_INSTALL_DIR}/lib")
+
+set(DEPS_BUILD_DIR "${CMAKE_BINARY_DIR}/build")
+set(DEPS_DOWNLOAD_DIR "${DEPS_BUILD_DIR}/downloads")
+
+set(DEPS_CMAKE_ARGS
+ -D CMAKE_C_COMPILER=${CMAKE_C_COMPILER}
+ -D CMAKE_C_STANDARD=99
+ -D CMAKE_GENERATOR=${CMAKE_GENERATOR}
+ -D CMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
+ -D BUILD_SHARED_LIBS=OFF
+ -D CMAKE_POSITION_INDEPENDENT_CODE=ON
+ -D CMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR})
+if(APPLE)
+ list(APPEND DEPS_CMAKE_ARGS -D CMAKE_FIND_FRAMEWORK=${CMAKE_FIND_FRAMEWORK})
+endif()
+
+set(DEPS_CMAKE_CACHE_ARGS -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES})
+
+# MAKE_PRG
+if(UNIX)
+ find_program(MAKE_PRG NAMES gmake make)
+ if(NOT MAKE_PRG)
+ message(FATAL_ERROR "GNU Make is required to build the dependencies.")
+ else()
+ message(STATUS "Found GNU Make at ${MAKE_PRG}")
+ endif()
+endif()
+# When using make, use the $(MAKE) variable to avoid warning about the job
+# server.
+if(CMAKE_GENERATOR MATCHES "Makefiles")
+ set(MAKE_PRG "$(MAKE)")
+endif()
+if(MINGW AND CMAKE_GENERATOR MATCHES "Ninja")
+ find_program(MAKE_PRG NAMES mingw32-make)
+ if(NOT MAKE_PRG)
+ message(FATAL_ERROR "GNU Make for mingw32 is required to build the dependencies.")
+ else()
+ message(STATUS "Found GNU Make for mingw32: ${MAKE_PRG}")
+ endif()
+endif()
+
+# DEPS_C_COMPILER
+set(DEPS_C_COMPILER "${CMAKE_C_COMPILER}")
+if(CMAKE_OSX_SYSROOT)
+ set(DEPS_C_COMPILER "${DEPS_C_COMPILER} -isysroot${CMAKE_OSX_SYSROOT}")
+endif()
+if(CMAKE_OSX_ARCHITECTURES)
+ foreach(ARCH IN LISTS CMAKE_OSX_ARCHITECTURES)
+ set(DEPS_C_COMPILER "${DEPS_C_COMPILER} -arch ${ARCH}")
+ endforeach()
+endif()
diff --git a/cmake/FindLibluv.cmake b/cmake/FindLibluv.cmake
deleted file mode 100644
index d402b26447..0000000000
--- a/cmake/FindLibluv.cmake
+++ /dev/null
@@ -1,14 +0,0 @@
-find_path(LIBLUV_INCLUDE_DIR luv/luv.h)
-find_library(LIBLUV_LIBRARY NAMES luv_a luv libluv_a)
-
-# Ubuntu-specific workaround to find system paths
-function(ubuntu)
- set(CMAKE_FIND_LIBRARY_PREFIXES "")
- find_path(LIBLUV_INCLUDE_DIR luv/luv.h PATH_SUFFIXES lua5.1)
- find_library(LIBLUV_LIBRARY NAMES luv PATH_SUFFIXES lua/5.1)
-endfunction()
-ubuntu()
-
-find_package_handle_standard_args(Libluv DEFAULT_MSG
- LIBLUV_LIBRARY LIBLUV_INCLUDE_DIR)
-mark_as_advanced(LIBLUV_INCLUDE_DIR LIBLUV_LIBRARY)
diff --git a/cmake/FindLibuv.cmake b/cmake/FindLibuv.cmake
index 0cf8da3061..fa1d51370f 100644
--- a/cmake/FindLibuv.cmake
+++ b/cmake/FindLibuv.cmake
@@ -1,13 +1,7 @@
find_path(LIBUV_INCLUDE_DIR uv.h)
-
-list(APPEND LIBUV_NAMES uv_a uv)
-
-find_library(LIBUV_LIBRARY NAMES ${LIBUV_NAMES})
+find_library(LIBUV_LIBRARY NAMES uv_a uv)
set(LIBUV_LIBRARIES ${LIBUV_LIBRARY})
-set(LIBUV_INCLUDE_DIRS ${LIBUV_INCLUDE_DIR})
-
-include(CheckLibraryExists)
check_library_exists(dl dlopen "dlfcn.h" HAVE_LIBDL)
if(HAVE_LIBDL)
diff --git a/cmake/FindLuajit.cmake b/cmake/FindLuajit.cmake
index 924e4c80d4..711c2c0c09 100644
--- a/cmake/FindLuajit.cmake
+++ b/cmake/FindLuajit.cmake
@@ -11,9 +11,6 @@ endif()
find_library(LUAJIT_LIBRARY NAMES ${LUAJIT_NAMES})
-set(LUAJIT_LIBRARIES ${LUAJIT_LIBRARY})
-set(LUAJIT_INCLUDE_DIRS ${LUAJIT_INCLUDE_DIR})
-
find_package_handle_standard_args(Luajit DEFAULT_MSG
LUAJIT_LIBRARY LUAJIT_INCLUDE_DIR)
diff --git a/cmake/FindLuv.cmake b/cmake/FindLuv.cmake
new file mode 100644
index 0000000000..ebd74887ed
--- /dev/null
+++ b/cmake/FindLuv.cmake
@@ -0,0 +1,14 @@
+find_path(LUV_INCLUDE_DIR luv/luv.h)
+find_library(LUV_LIBRARY NAMES luv_a luv libluv_a)
+
+# Ubuntu-specific workaround to find system paths
+function(ubuntu)
+ set(CMAKE_FIND_LIBRARY_PREFIXES "")
+ find_path(LUV_INCLUDE_DIR luv/luv.h PATH_SUFFIXES lua5.1)
+ find_library(LUV_LIBRARY NAMES luv PATH_SUFFIXES lua/5.1)
+endfunction()
+ubuntu()
+
+find_package_handle_standard_args(Luv DEFAULT_MSG
+ LUV_LIBRARY LUV_INCLUDE_DIR)
+mark_as_advanced(LUV_INCLUDE_DIR LUV_LIBRARY)
diff --git a/cmake/FindTreesitter.cmake b/cmake/FindTreesitter.cmake
index ddea35fe66..23214283c0 100644
--- a/cmake/FindTreesitter.cmake
+++ b/cmake/FindTreesitter.cmake
@@ -7,3 +7,23 @@ mark_as_advanced(TREESITTER_LIBRARY TREESITTER_INCLUDE_DIR)
add_library(treesitter INTERFACE)
target_include_directories(treesitter SYSTEM BEFORE INTERFACE ${TREESITTER_INCLUDE_DIR})
target_link_libraries(treesitter INTERFACE ${TREESITTER_LIBRARY})
+
+# TODO(lewis6991): remove when min TS version is 0.20.9
+list(APPEND CMAKE_REQUIRED_INCLUDES "${TREESITTER_INCLUDE_DIR}")
+list(APPEND CMAKE_REQUIRED_LIBRARIES "${TREESITTER_LIBRARY}")
+check_c_source_compiles("
+#include <tree_sitter/api.h>
+int
+main(void)
+{
+ TSQueryCursor *cursor = ts_query_cursor_new();
+ ts_query_cursor_set_max_start_depth(cursor, 32);
+ return 0;
+}
+" TS_HAS_SET_MAX_START_DEPTH)
+list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${TREESITTER_INCLUDE_DIR}")
+list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "${TREESITTER_LIBRARY}")
+
+if(TS_HAS_SET_MAX_START_DEPTH)
+ target_compile_definitions(treesitter INTERFACE NVIM_TS_HAS_SET_MAX_START_DEPTH)
+endif()
diff --git a/cmake/Format.cmake b/cmake/Format.cmake
index 4115e66705..7e8ca3547d 100644
--- a/cmake/Format.cmake
+++ b/cmake/Format.cmake
@@ -15,21 +15,21 @@ function(get_changed_files outvar)
# Changed files that have been committed
execute_process(
- COMMAND git diff --name-only ${ancestor_commit}...${current_branch}
+ COMMAND git diff --diff-filter=d --name-only ${ancestor_commit}...${current_branch}
OUTPUT_VARIABLE committed_files
OUTPUT_STRIP_TRAILING_WHITESPACE)
separate_arguments(committed_files NATIVE_COMMAND ${committed_files})
# Unstaged files
execute_process(
- COMMAND git diff --name-only
+ COMMAND git diff --diff-filter=d --name-only
OUTPUT_VARIABLE unstaged_files
OUTPUT_STRIP_TRAILING_WHITESPACE)
separate_arguments(unstaged_files NATIVE_COMMAND ${unstaged_files})
# Staged files
execute_process(
- COMMAND git diff --cached --name-only
+ COMMAND git diff --diff-filter=d --cached --name-only
OUTPUT_VARIABLE staged_files
OUTPUT_STRIP_TRAILING_WHITESPACE)
separate_arguments(staged_files NATIVE_COMMAND ${staged_files})
diff --git a/cmake/InstallHelpers.cmake b/cmake/InstallHelpers.cmake
index 49d8692aae..63bf2bb73b 100644
--- a/cmake/InstallHelpers.cmake
+++ b/cmake/InstallHelpers.cmake
@@ -7,9 +7,6 @@ if(CMAKE_SYSTEM_NAME MATCHES "BSD" AND NOT DEFINED CMAKE_INSTALL_MANDIR)
endif()
endif()
-# For $CMAKE_INSTALL_{DATAROOT,MAN, ...}DIR
-include(GNUInstallDirs)
-
# This will create any directories that need to be created in the destination
# path with the typical owner, group, and user permissions--independent of the
# umask setting.
diff --git a/cmake/LuaHelpers.cmake b/cmake/LuaHelpers.cmake
deleted file mode 100644
index 00ecd1357f..0000000000
--- a/cmake/LuaHelpers.cmake
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Functions to help checking for a Lua interpreter
-#
-
-# Check if a module is available in Lua
-function(check_lua_module LUA_PRG_PATH MODULE RESULT_VAR)
- execute_process(COMMAND ${LUA_PRG_PATH} -l "${MODULE}" -e ""
- RESULT_VARIABLE module_missing)
- if(module_missing)
- set(${RESULT_VAR} False PARENT_SCOPE)
- else()
- set(${RESULT_VAR} True PARENT_SCOPE)
- endif()
-endfunction()
diff --git a/cmake/RunTests.cmake b/cmake/RunTests.cmake
index fe346661b5..e1a0c8d6c3 100644
--- a/cmake/RunTests.cmake
+++ b/cmake/RunTests.cmake
@@ -63,7 +63,7 @@ if(NOT DEFINED ENV{TEST_TIMEOUT} OR "$ENV{TEST_TIMEOUT}" STREQUAL "")
endif()
set(ENV{SYSTEM_NAME} ${CMAKE_HOST_SYSTEM_NAME}) # used by test/helpers.lua.
-set(ENV{DEPS_PREFIX} ${DEPS_PREFIX}) # used by test/busted_runner.lua on windows
+set(ENV{DEPS_INSTALL_DIR} ${DEPS_INSTALL_DIR}) # used by test/busted_runner.lua
execute_process(
COMMAND ${NVIM_PRG} -ll ${WORKING_DIR}/test/busted_runner.lua -v -o test.busted.outputHandlers.${BUSTED_OUTPUT_TYPE}
@@ -82,7 +82,7 @@ execute_process(
file(GLOB RM_FILES ${BUILD_DIR}/Xtest_*)
file(REMOVE_RECURSE ${RM_FILES})
-if(NOT res EQUAL 0)
+if(res)
message(STATUS "Tests exited non-zero: ${res}")
if("${err}" STREQUAL "")
message(STATUS "No output to stderr.")
diff --git a/cmake/Util.cmake b/cmake/Util.cmake
index e15b44d29a..b70f33a302 100644
--- a/cmake/Util.cmake
+++ b/cmake/Util.cmake
@@ -193,3 +193,14 @@ function(set_default_buildtype)
endif()
endif()
endfunction()
+
+# Check if a module is available in Lua
+function(check_lua_module LUA_PRG_PATH MODULE RESULT_VAR)
+ execute_process(COMMAND ${LUA_PRG_PATH} -l "${MODULE}" -e ""
+ RESULT_VARIABLE module_missing)
+ if(module_missing)
+ set(${RESULT_VAR} FALSE PARENT_SCOPE)
+ else()
+ set(${RESULT_VAR} TRUE PARENT_SCOPE)
+ endif()
+endfunction()
diff --git a/contrib/asan.sh b/contrib/asan.sh
index baf7abb5a8..6354d65514 100755
--- a/contrib/asan.sh
+++ b/contrib/asan.sh
@@ -13,9 +13,6 @@ export CC='clang'
# Change to detect_leaks=1 to detect memory leaks (slower).
export ASAN_OPTIONS="detect_leaks=0:log_path=$log_path/asan"
-# Show backtraces in the logs.
-export UBSAN_OPTIONS="print_stacktrace=1"
-
make -C "$root_path" CMAKE_EXTRA_FLAGS="-DENABLE_ASAN_UBSAN=ON"
VIMRUNTIME="$root_path"/runtime "$root_path"/build/bin/nvim
diff --git a/contrib/flake.nix b/contrib/flake.nix
index d38d1fd2b7..59d977b748 100644
--- a/contrib/flake.nix
+++ b/contrib/flake.nix
@@ -106,7 +106,6 @@
# ASAN_OPTIONS=detect_leaks=1
export ASAN_OPTIONS="log_path=./test.log:abort_on_error=1"
- export UBSAN_OPTIONS=print_stacktrace=1
# for treesitter functionaltests
mkdir -p runtime/parser
diff --git a/runtime/autoload/netrw.vim b/runtime/autoload/netrw.vim
index 6c9938d8bb..c9f66f7927 100644
--- a/runtime/autoload/netrw.vim
+++ b/runtime/autoload/netrw.vim
@@ -1,7 +1,7 @@
" netrw.vim: Handles file transfer and remote directory listing across
" AUTOLOAD SECTION
-" Date: Mar 15, 2023
-" Version: 172
+" Date: May 03, 2023
+" Version: 173
" Maintainer: Charles E Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
" GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim
" Copyright: Copyright (C) 2016 Charles E. Campbell {{{1
@@ -43,7 +43,7 @@ if exists("s:needspatches")
endfor
endif
-let g:loaded_netrw = "v172"
+let g:loaded_netrw = "v173"
if !exists("s:NOTE")
let s:NOTE = 0
let s:WARNING = 1
@@ -5694,7 +5694,7 @@ fun! s:NetrwEditBuf(bufnum)
exe "sil! NetrwKeepj keepalt noswapfile b ".fnameescape(a:bufnum)
else
" call Decho("exe sil! NetrwKeepj noswapfile b ".fnameescape(a:bufnum))
- exe "sil! NetrwKeepj noswapfile b ".fnameescape(a:bufnume)
+ exe "sil! NetrwKeepj noswapfile b ".fnameescape(a:bufnum)
endif
" call Dret("s:NetrwEditBuf")
endfun
diff --git a/runtime/autoload/netrwSettings.vim b/runtime/autoload/netrwSettings.vim
index a910d18be8..d65f83144e 100644
--- a/runtime/autoload/netrwSettings.vim
+++ b/runtime/autoload/netrwSettings.vim
@@ -19,7 +19,7 @@
if exists("g:loaded_netrwSettings") || &cp
finish
endif
-let g:loaded_netrwSettings = "v18a"
+let g:loaded_netrwSettings = "v18"
if v:version < 700
echohl WarningMsg
echo "***warning*** this version of netrwSettings needs vim 7.0"
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 62afdc5830..f399f1ed25 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -411,7 +411,7 @@ use >lua
extid = vim.api.nvim_buf_set_extmark(buf, ns_id, line, col_start, {end_col = col_end, hl_group = hl_group})
-- example: modify the extmark's highlight group
- vim.api.nvim_buf_set_extmark(buf, ns_id, NEW_HL_GROUP, line, col_start, {end_col = col_end, hl_group = hl_group, id = extid})
+ vim.api.nvim_buf_set_extmark(buf, ns_id, line, col_start, {end_col = col_end, hl_group = NEW_HL_GROUP, id = extid})
-- example: change the highlight's position
vim.api.nvim_buf_set_extmark(buf, ns_id, NEW_LINE, col_start, {end_col = col_end, hl_group = NEW_HL_GROUP, id = extid})
@@ -486,7 +486,7 @@ Example: create a float with scratch buffer: >vim
\ 'row': 1, 'anchor': 'NW', 'style': 'minimal'}
let win = nvim_open_win(buf, 0, opts)
" optional: change highlight, otherwise Pmenu is used
- call nvim_win_set_option(win, 'winhl', 'Normal:MyHighlight')
+ call nvim_set_option_value('winhl', 'Normal:MyHighlight', {'win': win})
<
==============================================================================
@@ -1795,6 +1795,7 @@ nvim_create_user_command({name}, {command}, {*opts})
• fargs: (table) The args split by unescaped whitespace
(when more than one argument is allowed), if any
|<f-args>|
+ • nargs: (string) Number of arguments |:command-nargs|
• bang: (boolean) "true" if the command was executed with a
! modifier |<bang>|
• line1: (number) The starting line of the command range
@@ -1916,25 +1917,6 @@ nvim_parse_cmd({str}, {opts}) *nvim_parse_cmd()*
==============================================================================
Options Functions *api-options*
-nvim_buf_get_option({buffer}, {name}) *nvim_buf_get_option()*
- Gets a buffer option value
-
- Parameters: ~
- • {buffer} Buffer handle, or 0 for current buffer
- • {name} Option name
-
- Return: ~
- Option value
-
-nvim_buf_set_option({buffer}, {name}, {value}) *nvim_buf_set_option()*
- Sets a buffer option value. Passing `nil` as value deletes the option
- (only works if there's a global fallback)
-
- Parameters: ~
- • {buffer} Buffer handle, or 0 for current buffer
- • {name} Option name
- • {value} Option value
-
nvim_get_all_options_info() *nvim_get_all_options_info()*
Gets the option information for all options.
@@ -1944,15 +1926,6 @@ nvim_get_all_options_info() *nvim_get_all_options_info()*
Return: ~
dictionary of all options
-nvim_get_option({name}) *nvim_get_option()*
- Gets the global value of an option.
-
- Parameters: ~
- • {name} Option name
-
- Return: ~
- Option value (global)
-
nvim_get_option_info2({name}, {*opts}) *nvim_get_option_info2()*
Gets the option information for one option from arbitrary buffer or window
@@ -2009,13 +1982,6 @@ nvim_get_option_value({name}, {*opts}) *nvim_get_option_value()*
Return: ~
Option value
-nvim_set_option({name}, {value}) *nvim_set_option()*
- Sets the global value of an option.
-
- Parameters: ~
- • {name} Option name
- • {value} New option value
-
*nvim_set_option_value()*
nvim_set_option_value({name}, {value}, {*opts})
Sets the value of an option. The behavior of this function matches that of
@@ -2033,25 +1999,6 @@ nvim_set_option_value({name}, {value}, {*opts})
• win: |window-ID|. Used for setting window local option.
• buf: Buffer number. Used for setting buffer local option.
-nvim_win_get_option({window}, {name}) *nvim_win_get_option()*
- Gets a window option value
-
- Parameters: ~
- • {window} Window handle, or 0 for current window
- • {name} Option name
-
- Return: ~
- Option value
-
-nvim_win_set_option({window}, {name}, {value}) *nvim_win_set_option()*
- Sets a window option value. Passing `nil` as value deletes the option
- (only works if there's a global fallback)
-
- Parameters: ~
- • {window} Window handle, or 0 for current window
- • {name} Option name
- • {value} Option value
-
==============================================================================
Buffer Functions *api-buffer*
@@ -2661,6 +2608,8 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
• "overlay": display over the specified column, without
shifting the underlying text.
• "right_align": display right aligned in the window.
+ • "inline": display at the specified column, and shift the
+ buffer text to the right as needed
• virt_text_win_col : position the virtual text at a fixed
window column (starting from the first text column)
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index d0713ee18c..01e8cc964d 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -1162,7 +1162,7 @@ Set the 'cindent' option for C files in the /vim/src directory. >
If you have a link from "/tmp/test.c" to "/home/nobody/vim/src/test.c", and
you start editing "/tmp/test.c", this autocommand will match.
-Note: To match part of a path, but not from the root directory, use a '*' as
+Note: To match part of a path, but not from the root directory, use a "*" as
the first character. Example: >
:autocmd BufRead */doc/*.txt set tw=78
This autocommand will for example be executed for "/tmp/doc/xx.txt" and
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index c2dc5ddd5b..7acc764644 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -1888,7 +1888,7 @@ execute({command} [, {silent}]) *execute()*
The default is "silent". Note that with "silent!", unlike
`:redir`, error messages are dropped.
- To get a list of lines use |split()| on the result: >
+ To get a list of lines use `split()` on the result: >
execute('args')->split("\n")
< This function is not available in the |sandbox|.
@@ -6014,7 +6014,7 @@ printf({fmt}, {expr1} ...) *printf()*
be applied, see below.
A field width or precision, or both, may be indicated by an
- asterisk '*' instead of a digit string. In this case, a
+ asterisk "*" instead of a digit string. In this case, a
Number argument supplies the field width or precision. A
negative field width is treated as a left adjustment flag
followed by a positive field width; a negative precision is
@@ -6137,17 +6137,20 @@ prompt_setcallback({buf}, {expr}) *prompt_setcallback()*
that was entered at the prompt. This can be an empty string
if the user only typed Enter.
Example: >
- call prompt_setcallback(bufnr(''), function('s:TextEntered'))
func s:TextEntered(text)
if a:text == 'exit' || a:text == 'quit'
stopinsert
+ " Reset 'modified' to allow the buffer to be closed.
+ " We assume there is nothing useful to be saved.
+ set nomodified
close
else
+ " Do something useful with "a:text". In this example
+ " we just repeat it.
call append(line('$') - 1, 'Entered: "' .. a:text .. '"')
- " Reset 'modified' to allow the buffer to be closed.
- set nomodified
endif
endfunc
+ call prompt_setcallback(bufnr(), function('s:TextEntered'))
< Can also be used as a |method|: >
GetBuffer()->prompt_setcallback(callback)
@@ -9294,7 +9297,7 @@ win_execute({id}, {command} [, {silent}]) *win_execute()*
The window will temporarily be made the current window,
without triggering autocommands or changing directory. When
executing {command} autocommands will be triggered, this may
- have unexpected side effects. Use |:noautocmd| if needed.
+ have unexpected side effects. Use `:noautocmd` if needed.
Example: >
call win_execute(winid, 'syntax enable')
< Doing the same with `setwinvar()` would not trigger
diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt
index 844aab6fa3..c43d1caa0e 100644
--- a/runtime/doc/cmdline.txt
+++ b/runtime/doc/cmdline.txt
@@ -143,7 +143,7 @@ CTRL-R {register} *c_CTRL-R* *c_<C-R>*
the last delete or yank
'%' the current file name
'#' the alternate file name
- '*' the clipboard contents (X11: primary selection)
+ "*" the clipboard contents (X11: primary selection)
'+' the clipboard contents
'/' the last search pattern
':' the last command-line
@@ -431,8 +431,8 @@ CTRL-T When 'incsearch' is set, entering a search pattern for "/" or
keyboard T is above G.
The 'wildchar' option defaults to <Tab> (CTRL-E when in Vi compatible mode; in
-a previous version <Esc> was used). In the pattern standard wildcards '*' and
-'?' are accepted when matching file names. '*' matches any string, '?'
+a previous version <Esc> was used). In the pattern standard wildcards "*" and
+'?' are accepted when matching file names. "*" matches any string, '?'
matches exactly one character.
When repeating 'wildchar' or CTRL-N you cycle through the matches, eventually
diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt
index 3150190a8b..9d4a7324bf 100644
--- a/runtime/doc/deprecated.txt
+++ b/runtime/doc/deprecated.txt
@@ -21,6 +21,12 @@ API
- *nvim_get_hl_by_id()* Use |nvim_get_hl()| instead.
- *nvim_exec()* Use |nvim_exec2()| instead.
- *nvim_get_option_info()* Use |nvim_get_option_info2()| instead.
+- *nvim_buf_get_option()* Use |nvim_get_option_value()| instead.
+- *nvim_buf_set_option()* Use |nvim_set_option_value()| instead.
+- *nvim_get_option()* Use |nvim_get_option_value()| instead.
+- *nvim_set_option()* Use |nvim_set_option_value()| instead.
+- *nvim_win_get_option()* Use |nvim_get_option_value()| instead.
+- *nvim_win_set_option()* Use |nvim_set_option_value()| instead.
COMMANDS
- *:rv* *:rviminfo* Deprecated alias to |:rshada| command.
diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt
index bd1b62635e..c774d1ad38 100644
--- a/runtime/doc/editing.txt
+++ b/runtime/doc/editing.txt
@@ -1581,7 +1581,7 @@ There are three different types of searching:
so they work on all operating systems. Note that "**" only acts as a
special wildcard when it is at the start of a name.
- The usage of '*' is quite simple: It matches 0 or more characters. In a
+ The usage of "*" is quite simple: It matches 0 or more characters. In a
search pattern this would be ".*". Note that the "." is not used for file
searching.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 05fdf2f5bb..aa53244dc8 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1087,7 +1087,7 @@ That works, since the String "190" is automatically converted to the Number
1 . 90 * 90.0
Should be read as: >
1 . (90 * 90.0)
-Since '.' has lower precedence than '*'. This does NOT work, since this
+Since '.' has lower precedence than "*". This does NOT work, since this
attempts to concatenate a Float and a String.
When dividing a Number by zero the result depends on the value:
@@ -2210,7 +2210,7 @@ v:register The name of the register in effect for the current normal mode
(use this in custom commands that take a register).
If none is supplied it is the default register '"', unless
'clipboard' contains "unnamed" or "unnamedplus", then it is
- '*' or '+'.
+ "*" or '+'.
Also see |getreg()| and |setreg()|
*v:relnum* *relnum-variable*
@@ -4270,10 +4270,10 @@ The input is in the variable "line", the results in the variables "file",
getting the scriptnames in a Dictionary ~
*scriptnames-dictionary*
-The |:scriptnames| command can be used to get a list of all script files that
-have been sourced. There is no equivalent function or variable for this
-(because it's rarely needed). In case you need to manipulate the list this
-code can be used: >
+The `:scriptnames` command can be used to get a list of all script files that
+have been sourced. There is also the `getscriptinfo()` function, but the
+information returned is not exactly the same. In case you need to manipulate
+the output of `scriptnames` this code can be used: >
" Get the output of ":scriptnames" in the scriptnames_output variable.
let scriptnames_output = ''
redir => scriptnames_output
diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt
index 175c531950..48d6aed0f2 100644
--- a/runtime/doc/filetype.txt
+++ b/runtime/doc/filetype.txt
@@ -162,6 +162,7 @@ variables can be used to overrule the filetype used for certain extensions:
*.sys g:filetype_sys
*.sh g:bash_is_sh |ft-sh-syntax|
*.tex g:tex_flavor |ft-tex-plugin|
+ *.typ g:filetype_typ
*.w g:filetype_w |ft-cweb-syntax|
For a few filetypes the global variable is used only when the filetype could
diff --git a/runtime/doc/ft_raku.txt b/runtime/doc/ft_raku.txt
index 3d1179ed4e..3fafa6e224 100644
--- a/runtime/doc/ft_raku.txt
+++ b/runtime/doc/ft_raku.txt
@@ -35,7 +35,7 @@ Some of them are available with standard Vim digraphs:
(- ∈ ?= ≅ != ≠ ~
-) ∋ ?- ≃ ~
-The Greek alphabet is available with '*' followed by a similar Latin symbol:
+The Greek alphabet is available with "*" followed by a similar Latin symbol:
*p π ~
*t τ ~
*X × ~
diff --git a/runtime/doc/helphelp.txt b/runtime/doc/helphelp.txt
index da307dd241..ca26332017 100644
--- a/runtime/doc/helphelp.txt
+++ b/runtime/doc/helphelp.txt
@@ -167,7 +167,7 @@ The initial height of the help window can be set with the 'helpheight' option
*help-buffer-options*
When the help buffer is created, several local options are set to make sure
the help text is displayed as it was intended:
- 'iskeyword' nearly all ASCII chars except ' ', '*', '"' and '|'
+ 'iskeyword' nearly all ASCII chars except ' ', "*", '"' and '|'
'foldmethod' "manual"
'tabstop' 8
'arabic' off
diff --git a/runtime/doc/if_pyth.txt b/runtime/doc/if_pyth.txt
index 415a58ec71..a96c9fcc0a 100644
--- a/runtime/doc/if_pyth.txt
+++ b/runtime/doc/if_pyth.txt
@@ -17,7 +17,7 @@ Commands *python-commands*
:[range]py[thon] {stmt}
Execute Python statement {stmt}. A simple check if
the `:python` command is working: >vim
- :python print "Hello"
+ :python print("Hello")
:[range]py[thon] << [trim] [{endmarker}]
{script}
@@ -35,7 +35,7 @@ Example: >vim
python << EOF
class StrawberryIcecream:
def __call__(self):
- print 'EAT ME'
+ print('EAT ME')
EOF
endfunction
@@ -100,11 +100,9 @@ To pass arguments you need to set sys.argv[] explicitly. Example: >vim
Here are some examples *python-examples*
>vim
-
:python from vim import *
- :python from string import upper
- :python current.line = upper(current.line)
- :python print "Hello"
+ :python current.line = str.upper(current.line)
+ :python print("Hello")
:python str = current.buffer[42]
Note that changes (such as the "import" statements) persist from one command
@@ -112,26 +110,16 @@ to the next, just like the Python REPL.
*script-here*
When using a script language in-line, you might want to skip this when the
-language isn't supported. Note that this mechanism doesn't work:
+language isn't supported.
>vim
if has('python')
python << EOF
- this will NOT work!
+ print("python works")
EOF
endif
-
-Instead, put the Python command in a function and call that function:
->vim
- if has('python')
- function DefPython()
- python << EOF
- this works
- EOF
- endfunction
- call DefPython()
- endif
-
-Note that "EOF" must be at the start of the line.
+<
+Note that "EOF" must be at the start of the line without preceding white
+space.
==============================================================================
The vim module *python-vim*
@@ -143,7 +131,7 @@ module before using it: >vim
:python import vim
Overview >vim
- :py print "Hello" # displays a message
+ :py print("Hello") # displays a message
:py vim.command(cmd) # execute an Ex command
:py w = vim.windows[n] # gets window "n"
:py cw = vim.current.window # gets the current window
@@ -175,10 +163,6 @@ vim.command(str) *python-command*
# Note the use of single quotes to delimit a string containing
# double quotes
normal('"a2dd"aP')
-< *E659*
- The ":python" command cannot be used recursively with Python 2.2 and
- older. This only works with Python 2.3 and later: >vim
- :py vim.command("python print 'Hello again Python'")
vim.eval(str) *python-eval*
Evaluates the expression str using the vim internal expression
@@ -190,8 +174,8 @@ vim.eval(str) *python-eval*
Examples: >vim
:py text_width = vim.eval("&tw")
:py str = vim.eval("12+12") # NB result is a string! Use
- # string.atoi() to convert to
- # a number.
+ # int() to convert to a
+ # number.
vim.strwidth(str) *python-strwidth*
Like |strwidth()|: returns number of display cells str occupies, tab
@@ -467,7 +451,7 @@ A trailing '\n' is allowed and ignored, so that you can do: >vim
Buffer object type is available using "Buffer" attribute of vim module.
Examples (assume b is the current buffer) >vim
- :py print b.name # write the buffer file name
+ :py print(b.name) # write the buffer file name
:py b[0] = "hello!!!" # replace the top line
:py b[:] = None # delete the whole buffer
:py del b[:] # delete the whole buffer
diff --git a/runtime/doc/indent.txt b/runtime/doc/indent.txt
index f3e196b426..ccff09d7fc 100644
--- a/runtime/doc/indent.txt
+++ b/runtime/doc/indent.txt
@@ -112,7 +112,7 @@ e Reindent a line that starts with "else" when you type the second 'e'.
=~word Like =word, but ignore case.
If you really want to reindent when you type 'o', 'O', 'e', '0', '<', '>',
-'*', ':' or '!', use "<o>", "<O>", "<e>", "<0>", "<<>", "<>>", "<*>", "<:>" or
+"*", ':' or '!', use "<o>", "<O>", "<e>", "<0>", "<<>", "<>>", "<*>", "<:>" or
"<!>", respectively, for those keys.
For an emacs-style indent mode where lines aren't indented every time you
diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt
index 49aa2a79a4..de1b850a3f 100644
--- a/runtime/doc/insert.txt
+++ b/runtime/doc/insert.txt
@@ -114,7 +114,7 @@ CTRL-R {register} *i_CTRL-R*
the last delete or yank
'%' the current file name
'#' the alternate file name
- '*' the clipboard contents (X11: primary selection)
+ "*" the clipboard contents (X11: primary selection)
'+' the clipboard contents
'/' the last search pattern
':' the last command-line
@@ -1392,7 +1392,7 @@ other versions of HTML. Features:
- after "<" complete tag name depending on context (no div suggestion inside
of an a tag); '/>' indicates empty tags
- inside of tag complete proper attributes (no width attribute for an a tag);
- show also type of attribute; '*' indicates required attributes
+ show also type of attribute; "*" indicates required attributes
- when attribute has limited number of possible values help to complete them
- complete names of entities
- complete values of "class" and "id" attributes with data obtained from
diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt
index 685c953718..15fe3838b7 100644
--- a/runtime/doc/intro.txt
+++ b/runtime/doc/intro.txt
@@ -385,7 +385,7 @@ Note:
combinations actually work depends on the UI or host terminal.
- When a key is pressed using a meta or alt modifier and no mapping exists for
that keypress, Nvim may behave as though <Esc> was pressed before the key.
-- It is possible to notate combined modifiers (e.g. <C-A-T> for CTRL-ALT-T),
+- It is possible to notate combined modifiers (e.g. <M-C-T> for CTRL-ALT-T),
but your terminal must encode the input for that to work. |tui-input|
*<>*
diff --git a/runtime/doc/job_control.txt b/runtime/doc/job_control.txt
index 37a4e2ebb1..d99c76ab22 100644
--- a/runtime/doc/job_control.txt
+++ b/runtime/doc/job_control.txt
@@ -134,9 +134,6 @@ To send data to the job's stdin, use |chansend()|: >vim
:call chansend(job1, "invalid-command\n")
:call chansend(job1, "exit\n")
<
-A job may be killed with |jobstop()|: >vim
- :call jobstop(job1)
-<
A job may be killed at any time with the |jobstop()| function:
>vim
:call jobstop(job1)
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index e07bfc2209..98a0801013 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -800,8 +800,8 @@ formatexpr({opts}) *vim.lsp.formatexpr()*
Currently only supports a single client. This can be set via `setlocal
formatexpr=v:lua.vim.lsp.formatexpr()` but will typically or in
- `on_attach` via `vim.api.nvim_buf_set_option(bufnr, 'formatexpr',
- 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})')`.
+ `on_attach` via `vim.bo[bufnr].formatexpr =
+ 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'`.
Parameters: ~
• {opts} (table) options for customizing the formatting expression
@@ -942,20 +942,20 @@ start_client({config}) *vim.lsp.start_client()*
Parameters: ~
• {config} (table) Configuration for the server:
- • cmd: (table|string|fun(dispatchers: table):table) command
- string or list treated like |jobstart()|. The command must
- launch the language server process. `cmd` can also be a
- function that creates an RPC client. The function receives
- a dispatchers table and must return a table with the
- functions `request`, `notify`, `is_closing` and
+ • cmd: (string[]|fun(dispatchers: table):table) command a
+ list of strings treated like |jobstart()|. The command
+ must launch the language server process. `cmd` can also be
+ a function that creates an RPC client. The function
+ receives a dispatchers table and must return a table with
+ the functions `request`, `notify`, `is_closing` and
`terminate` See |vim.lsp.rpc.request()| and
|vim.lsp.rpc.notify()| For TCP there is a built-in rpc
client factory: |vim.lsp.rpc.connect()|
• cmd_cwd: (string, default=|getcwd()|) Directory to launch
the `cmd` process. Not related to `root_dir`.
• cmd_env: (table) Environment flags to pass to the LSP on
- spawn. Must be specified using a map-like table.
- Non-string values are coerced to string. Example: >
+ spawn. Must be specified using a table. Non-string values
+ are coerced to string. Example: >
{ PORT = 8080; HOST = "0.0.0.0"; }
<
@@ -1299,13 +1299,6 @@ rename({new_name}, {options}) *vim.lsp.buf.rename()*
• name (string|nil): Restrict clients used for rename to
ones where client.name matches this field.
-server_ready() *vim.lsp.buf.server_ready()*
- Checks whether the language servers attached to the current buffer are
- ready.
-
- Return: ~
- `true` if server responds.
-
signature_help() *vim.lsp.buf.signature_help()*
Displays signature information about the symbol under the cursor in a
floating window.
diff --git a/runtime/doc/lua-guide.txt b/runtime/doc/lua-guide.txt
index 3c2e1ac3d1..94db6aac0a 100644
--- a/runtime/doc/lua-guide.txt
+++ b/runtime/doc/lua-guide.txt
@@ -624,9 +624,9 @@ in a different file:
>lua
local mygroup = vim.api.nvim_create_augroup('vimrc', { clear = false })
vim.api.nvim_create_autocmd({ 'BufNewFile', 'BufRead' }, {
- pattern = '*.html',
+ pattern = '*.c',
group = mygroup,
- command = 'set shiftwidth=4',
+ command = 'set noexpandtab',
})
<
------------------------------------------------------------------------------
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index d9952205da..ad9cb69ae0 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -321,20 +321,22 @@ Example: >vim
:echo luaeval('string.match(_A, "[a-z]+")', 'XYXfoo123')
" foo
<
+ *lua-table*
Lua tables are used as both dictionaries and lists, so it is impossible to
determine whether empty table is meant to be empty list or empty dictionary.
Additionally Lua does not have integer numbers. To distinguish between these
cases there is the following agreement:
-
+ *lua-list*
0. Empty table is empty list.
1. Table with N incrementally growing integral numbers, starting from 1 and
ending with N is considered to be a list.
+ *lua-dict*
2. Table with string keys, none of which contains NUL byte, is considered to
be a dictionary.
3. Table with string keys, at least one of which contains NUL byte, is also
considered to be a dictionary, but this time it is converted to
a |msgpack-special-map|.
- *lua-special-tbl*
+ *lua-special-tbl*
4. Table with `vim.type_idx` key may be a dictionary, a list or floating-point
value:
- `{[vim.type_idx]=vim.types.float, [vim.val_idx]=1}` is converted to
@@ -399,7 +401,7 @@ For example consider the following Lua omnifunc handler: >lua
return {'stuff', 'steam', 'strange things'}
end
end
- vim.api.nvim_buf_set_option(0, 'omnifunc', 'v:lua.mymod.omnifunc')
+ vim.bo[buf].omnifunc = 'v:lua.mymod.omnifunc'
Note: The module ("mymod" in the above example) must either be a Lua global,
or use require() as shown above to access it from a package.
@@ -1432,7 +1434,7 @@ keycode({str}) *vim.keycode()*
• |nvim_replace_termcodes()|
lua_omnifunc({find_start}, {_}) *vim.lua_omnifunc()*
- Omnifunc for completing lua values from from the runtime lua interpreter,
+ Omnifunc for completing lua values from the runtime lua interpreter,
similar to the builtin completion for the `:lua` command.
Activate using `set omnifunc=v:lua.vim.lua_omnifunc` in a lua buffer.
@@ -1881,7 +1883,7 @@ tbl_count({t}) *vim.tbl_count()*
• https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua
tbl_deep_extend({behavior}, {...}) *vim.tbl_deep_extend()*
- Merges recursively two or more map-like tables.
+ Merges recursively two or more tables.
Parameters: ~
• {behavior} (string) Decides what to do if a key is found in more than
@@ -1889,7 +1891,7 @@ tbl_deep_extend({behavior}, {...}) *vim.tbl_deep_extend()*
• "error": raise an error
• "keep": use value from the leftmost map
• "force": use value from the rightmost map
- • {...} (table) Two or more map-like tables
+ • {...} (table) Two or more tables
Return: ~
(table) Merged table
@@ -1898,7 +1900,7 @@ tbl_deep_extend({behavior}, {...}) *vim.tbl_deep_extend()*
• |vim.tbl_extend()|
tbl_extend({behavior}, {...}) *vim.tbl_extend()*
- Merges two or more map-like tables.
+ Merges two or more tables.
Parameters: ~
• {behavior} (string) Decides what to do if a key is found in more than
@@ -1906,7 +1908,7 @@ tbl_extend({behavior}, {...}) *vim.tbl_extend()*
• "error": raise an error
• "keep": use value from the leftmost map
• "force": use value from the rightmost map
- • {...} (table) Two or more map-like tables
+ • {...} (table) Two or more tables
Return: ~
(table) Merged table
@@ -2574,6 +2576,16 @@ find({names}, {opts}) *vim.fs.find()*
(table) Normalized paths |vim.fs.normalize()| of all matching files or
directories
+joinpath({...}) *vim.fs.joinpath()*
+ Concatenate directories and/or file into a single path with normalization
+ (e.g., `"foo/"` and `"bar"` get joined to `"foo/bar"`)
+
+ Parameters: ~
+ • {...} (string)
+
+ Return: ~
+ (string)
+
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
@@ -2728,7 +2740,7 @@ versions (1.2.3-rc1) are not matched. >
<
cmp({v1}, {v2}) *vim.version.cmp()*
- Parses and compares two version version objects (the result of
+ Parses and compares two version objects (the result of
|vim.version.parse()|, or specified literally as a `{major, minor, patch}`
tuple, e.g. `{1, 0, 3}`).
diff --git a/runtime/doc/luvref.txt b/runtime/doc/luvref.txt
index 799d0f6f74..79dd1248aa 100644
--- a/runtime/doc/luvref.txt
+++ b/runtime/doc/luvref.txt
@@ -2917,7 +2917,7 @@ uv.fs_fstat({fd} [, {callback}]) *uv.fs_fstat()*
uv.fs_lstat({path} [, {callback}]) *uv.fs_lstat()*
Parameters:
- - `fd`: `integer`
+ - `path`: `string`
- `callback`: `callable` (async version) or `nil` (sync
version)
- `err`: `nil` or `string`
@@ -3499,6 +3499,65 @@ uv.thread_equal({thread}, {other_thread}) *uv.thread_equal()*
This function is equivalent to the `__eq` metamethod.
Returns: `boolean`
+ *uv.thread_setaffinity()*
+uv.thread_setaffinity({thread}, {affinity} [, {get_old_affinity}])
+
+ > method form `thread:setaffinity(affinity, [get_old_affinity])`
+
+ Parameters:
+ - `thread`: `luv_thread_t userdata`
+ - `affinity`: `table`
+ - `[1, 2, 3, ..., n]` : `boolean`
+ - `get_old_affinity`: `boolean`
+
+ Sets the specified thread's affinity setting. `affinity` must
+ be an array-like table where each of the keys correspond to a
+ CPU number and the values are booleans that represent whether
+ the `thread` should be eligible to run on that CPU. The length
+ of the `affinity` table must be greater than or equal to
+ `uv.cpumask_size()`. If `get_old_affinity` is `true`, the
+ previous affinity settings for the `thread` will be returned.
+ Otherwise, `true` is returned after a successful call.
+
+ Note: Thread affinity setting is not atomic on Windows.
+ Unsupported on macOS.
+
+ Returns: `table` or `boolean` or `fail`
+ - `[1, 2, 3, ..., n]` : `boolean`
+
+
+uv.thread_getaffinity({thread} [, {mask_size}]) *uv.thread_getaffinity()*
+
+ > method form `thread:getaffinity([mask_size])`
+
+ Parameters:
+ - `thread`: `luv_thread_t userdata`
+ - `mask_size`: `integer`
+
+ Gets the specified thread's affinity setting.
+
+ If `mask_size` is provided, it must be greater than or equal
+ to `uv.cpumask_size()`. If the `mask_size` parameter is
+ omitted, then the return of `uv.cpumask_size()` will be used.
+ Returns an array-like table where each of the keys correspond
+ to a CPU number and the values are booleans that represent
+ whether the `thread` is eligible to run on that CPU.
+
+ Note: Thread affinity getting is not atomic on Windows.
+ Unsupported on macOS.
+
+ Returns: `table` or `fail`
+ - `[1, 2, 3, ..., n]` : `boolean`
+
+uv.thread_getcpu() *uv.thread_getcpu()*
+
+ Gets the CPU number on which the calling thread is running.
+
+ Note: The first CPU will be returned as the number 1, not 0.
+ This allows for the number to correspond with the table keys
+ used in `uv.thread_getaffinity` and `uv.thread_setaffinity`.
+
+ Returns: `integer` or `fail`
uv.thread_self() *uv.thread_self()*
@@ -3588,6 +3647,16 @@ uv.get_constrained_memory() *uv.get_constrained_memory()*
Returns: `number`
+uv.get_available_memory() *uv.get_available_memory()*
+
+ Gets the amount of free memory that is still available to the
+ process (in bytes). This differs from `uv.get_free_memory()`
+ in that it takes into account any limits imposed by the OS. If
+ there is no such constraint, or the constraint is unknown, the
+ amount returned will be identical to `uv.get_free_memory()`.
+
+ Returns: `number`
+
uv.resident_set_memory() *uv.resident_set_memory()*
Returns the resident set size (RSS) for the current process.
@@ -3652,6 +3721,14 @@ uv.cpu_info() *uv.cpu_info()*
- `idle` : `number`
- `irq` : `number`
+uv.cpumask_size() *uv.cpumask_size()*
+
+ Returns the maximum size of the mask used for process/thread
+ affinities, or `ENOTSUP` if affinities are not supported on
+ the current platform.
+
+ Returns: `integer` or `fail`
+
uv.getpid() *uv.getpid()*
DEPRECATED: Please use |uv.os_getpid()| instead.
@@ -3708,6 +3785,25 @@ uv.hrtime() *uv.hrtime()*
Returns: `number`
+uv.clock_gettime({clock_id}) *uv.clock_gettime()*
+
+ Parameters:
+ - `clock_id`: `string`
+
+ Obtain the current system time from a high-resolution
+ real-time or monotonic clock source. `clock_id` can be the
+ string `"monotonic"` or `"realtime"`.
+
+ The real-time clock counts from the UNIX epoch (1970-01-01)
+ and is subject to time adjustments; it can jump back in time.
+
+ The monotonic clock counts from an arbitrary point in the past
+ and never jumps back in time.
+
+ Returns: `table` or `fail`
+ - `sec`: `integer`
+ - `nsec`: `integer`
+
uv.uptime() *uv.uptime()*
Returns the current system uptime in seconds.
@@ -3979,6 +4075,22 @@ uv.metrics_idle_time() *uv.metrics_idle_time()*
Returns: `number`
+uv.metrics_info() *uv.metrics_info()*
+
+ Get the metrics table from current set of event loop metrics.
+
+ Returns: `table`
+
+ The table contains event loop metrics. It is recommended to
+ retrieve these metrics in a uv_prepare_cb in order to make
+ sure there are no inconsistencies with the metrics counters.
+
+ - `loop_count` : `integer`
+ - `events` : `integer`
+ - `events_waiting` : `integer`
+
+ Note: New in libuv version 1.45.0.
+
==============================================================================
CREDITS *luv-credits*
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt
index 164e2d4ec5..ad7901b962 100644
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -290,7 +290,7 @@ Therefore the following is blocked for <expr> mappings:
- Moving the cursor is allowed, but it is restored afterwards.
- If the cmdline is changed, the old text and cursor position are restored.
If you want the mapping to do any of these let the returned characters do
-that. (Or use a |<Cmd>| mapping instead.)
+that, or use a |<Cmd>| mapping instead.
You can use getchar(), it consumes typeahead if there is any. E.g., if you
have these mappings: >
@@ -324,20 +324,22 @@ be seen as a special key.
*<Cmd>* *:map-cmd*
The <Cmd> pseudokey begins a "command mapping", which executes the command
-directly (without changing modes). Where you might use ":...<CR>" in the
+directly without changing modes. Where you might use ":...<CR>" in the
{rhs} of a mapping, you can instead use "<Cmd>...<CR>".
Example: >
- noremap x <Cmd>echo mode(1)<cr>
+ noremap x <Cmd>echo mode(1)<CR>
<
-This is more flexible than `:<C-U>` in visual and operator-pending mode, or
-`<C-O>:` in insert-mode, because the commands are executed directly in the
-current mode (instead of always going to normal-mode). Visual-mode is
+This is more flexible than `:<C-U>` in Visual and Operator-pending mode, or
+`<C-O>:` in Insert mode, because the commands are executed directly in the
+current mode, instead of always going to Normal mode. Visual mode is
preserved, so tricks with |gv| are not needed. Commands can be invoked
-directly in cmdline-mode (which would otherwise require timer hacks).
+directly in Command-line mode (which would otherwise require timer hacks).
+Example of using <Cmd> halfway Insert mode: >
+ nnoremap <F3> aText <Cmd>echo mode(1)<CR> Added<Esc>
Unlike <expr> mappings, there are no special restrictions on the <Cmd>
command: it is executed as if an (unrestricted) |autocommand| was invoked
-or an async event event was processed.
+or an async event was processed.
Note:
- Because <Cmd> avoids mode-changes (unlike ":") it does not trigger
@@ -350,7 +352,7 @@ Note:
- In Visual mode you can use `line('v')` and `col('v')` to get one end of the
Visual area, the cursor is at the other end.
- *E5520*
+ *E1255* *E1136*
<Cmd> commands must terminate, that is, they must be followed by <CR> in the
{rhs} of the mapping definition. |Command-line| mode is never entered.
@@ -636,6 +638,7 @@ not to be matched with any key sequence. This is useful in plugins
*<MouseMove>*
The special key name "<MouseMove>" can be used to handle mouse movement. It
needs to be enabled with 'mousemoveevent'.
+The |getmousepos()| function can be used to obtain the mouse position.
*<Char>* *<Char->*
To map a character by its decimal, octal or hexadecimal number the <Char>
@@ -1727,8 +1730,12 @@ remains unmodified. Also see |f-args-example| below. Overview:
XX a\\\ b 'a\ b'
XX a\\\\b 'a\\b'
XX a\\\\ b 'a\\', 'b'
+ XX [nothing]
+Note that if the "no arguments" situation is to be handled, you have to make
+sure that the function can be called without arguments.
+
Examples for user commands: >
" Delete everything after here to the end
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index bc357ac534..795ccc55de 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -29,6 +29,7 @@ The following changes may require adaptations in user config or plugins.
set selectmode=mouse,key
set mousemodel=popup
set keymodel=startsel,stopsel
+<
==============================================================================
ADDED FEATURES *news-added*
@@ -36,7 +37,7 @@ ADDED FEATURES *news-added*
The following new APIs or features were added.
• |vim.iter()| provides a generic iterator interface for tables and Lua
-iterators |luaref-in|.
+ iterators |luaref-in|.
• Added |vim.keycode()| for translating keycodes in a string.
@@ -50,7 +51,16 @@ iterators |luaref-in|.
default).
• |'smoothscroll'| option to scroll by screen line rather than by text line
-when |'wrap'| is set.
+ when |'wrap'| is set.
+
+• |Query:iter_matches()| now has the ability to set the maximum start depth
+ for matches.
+
+• Added inline virtual text support to |nvim_buf_set_extmark()|.
+
+• The terminal buffer now supports reflow (wrapped lines adapt when the buffer
+ is resized horizontally). Note: Lines that are not visible and kept in
+ |'scrollback'| are not reflown.
==============================================================================
CHANGED FEATURES *news-changed*
@@ -80,14 +90,22 @@ The following deprecated functions or APIs were removed.
==============================================================================
DEPRECATIONS *news-deprecations*
-The following functions are now deprecated and will be removed in the next
+The following functions are now deprecated and will be removed in a future
release.
• Checkhealth functions:
- - |health#report_error|, |vim.health.report_error()| Use Lua |vim.health.error()| instead.
- - |health#report_info|, |vim.health.report_info()| Use Lua |vim.health.info()| instead.
- - |health#report_ok|, |vim.health.report_ok()| Use Lua |vim.health.ok()| instead.
- - |health#report_start|, |vim.health.report_start()| Use Lua |vim.health.start()| instead.
- - |health#report_warn|, |vim.health.report_warn()| Use Lua |vim.health.warn()| instead.
+ - |health#report_error|, |vim.health.report_error()| Use |vim.health.error()| instead.
+ - |health#report_info|, |vim.health.report_info()| Use |vim.health.info()| instead.
+ - |health#report_ok|, |vim.health.report_ok()| Use |vim.health.ok()| instead.
+ - |health#report_start|, |vim.health.report_start()| Use |vim.health.start()| instead.
+ - |health#report_warn|, |vim.health.report_warn()| Use |vim.health.warn()| instead.
+
+• |API| functions:
+ - |nvim_buf_get_option()| Use |nvim_get_option_value()| instead.
+ - |nvim_buf_set_option()| Use |nvim_set_option_value()| instead.
+ - |nvim_get_option()| Use |nvim_get_option_value()| instead.
+ - |nvim_set_option()| Use |nvim_set_option_value()| instead.
+ - |nvim_win_get_option()| Use |nvim_get_option_value()| instead.
+ - |nvim_win_set_option()| Use |nvim_set_option_value()| instead.
vim:tw=78:ts=8:sw=2:et:ft=help:norl:
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index c87b6f1835..72463af418 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -706,6 +706,9 @@ A jump table for the options with a short description can be found at |Q_op|.
'autowriteall' for that.
Some buffers will not be written, specifically when 'buftype' is
"nowrite", "nofile", "terminal" or "prompt".
+ USE WITH CARE: If you make temporary changes to a buffer that you
+ don't want to be saved this option may cause it to be saved anyway.
+ Renaming the buffer with ":file {name}" may help avoid this.
*'autowriteall'* *'awa'* *'noautowriteall'* *'noawa'*
'autowriteall' 'awa' boolean (default off)
@@ -1324,7 +1327,7 @@ A jump table for the options with a short description can be found at |Q_op|.
register. When "unnamed" is also included to the
option, yank and delete operations (but not put)
will additionally copy the text into register
- '*'. See |clipboard|.
+ "*". See |clipboard|.
*'cmdheight'* *'ch'*
'cmdheight' 'ch' number (default 1)
@@ -3523,7 +3526,7 @@ A jump table for the options with a short description can be found at |Q_op|.
that is not white space or punctuation).
For C programs you could use "a-z,A-Z,48-57,_,.,-,>".
For a help file it is set to all non-blank printable characters except
- '*', '"' and '|' (so that CTRL-] on a command finds the help for that
+ "*", '"' and '|' (so that CTRL-] on a command finds the help for that
command).
When the 'lisp' option is on the '-' character is always included.
This option also influences syntax highlighting, unless the syntax
@@ -4910,6 +4913,9 @@ A jump table for the options with a short description can be found at |Q_op|.
Minimum is 1, maximum is 100000.
Only in |terminal| buffers.
+ Note: Lines that are not visible and kept in scrollback are not
+ reflown when the terminal buffer is resized horizontally.
+
*'scrollbind'* *'scb'* *'noscrollbind'* *'noscb'*
'scrollbind' 'scb' boolean (default off)
local to window
@@ -6201,16 +6207,18 @@ A jump table for the options with a short description can be found at |Q_op|.
'switchbuf' 'swb' string (default "uselast")
global
This option controls the behavior when switching between buffers.
- Mostly for |quickfix| commands some values are also used for other
- commands, as mentioned below.
+ This option is checked, when
+ - jumping to errors with the |quickfix| commands (|:cc|, |:cn|, |:cp|,
+ etc.)
+ - jumping to a tag using the |:stag| command.
+ - opening a file using the |CTRL-W_f| or |CTRL-W_F| command.
+ - jumping to a buffer using a buffer split command (e.g. |:sbuffer|,
+ |:sbnext|, or |:sbrewind|).
Possible values (comma-separated list):
- useopen If included, jump to the first open window that
- contains the specified buffer (if there is one).
- Otherwise: Do not examine other windows.
- This setting is checked with |quickfix| commands, when
- jumping to errors (":cc", ":cn", "cp", etc.). It is
- also used in all buffer related split commands, for
- example ":sbuffer", ":sbnext", or ":sbrewind".
+ useopen If included, jump to the first open window in the
+ current tab page that contains the specified buffer
+ (if there is one). Otherwise: Do not examine other
+ windows.
usetab Like "useopen", but also consider windows in other tab
pages.
split If included, split the current window before loading
diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt
index 0742071d12..276041caac 100644
--- a/runtime/doc/pi_netrw.txt
+++ b/runtime/doc/pi_netrw.txt
@@ -208,7 +208,7 @@ EXTERNAL APPLICATIONS AND PROTOCOLS *netrw-externapp* {{{2
http: g:netrw_http_cmd = "links" elseif links is available
http: g:netrw_http_cmd = "curl" elseif curl is available
http: g:netrw_http_cmd = "wget" elseif wget is available
- http: g:netrw_http_cmd = "fetch" elseif fetch is available
+ http: g:netrw_http_cmd = "fetch" elseif fetch is available
http: *g:netrw_http_put_cmd* = "curl -T"
rcp: *g:netrw_rcp_cmd* = "rcp"
rsync: *g:netrw_rsync_cmd* = "rsync" (see |g:netrw_rsync_sep|)
@@ -968,7 +968,7 @@ itself:
fun! NetReadFixup(method, line1, line2)
if method == 3 " ftp (no <.netrc>)
let fourblanklines= line2 - 3
- silent fourblanklines.",".line2."g/^\s*/d"
+ silent fourblanklines .. "," .. line2 .. "g/^\s*/d"
endif
endfunction
endif
@@ -1625,8 +1625,10 @@ A further approach is to delete files which match a pattern.
This will cause the matching files to be marked. Then,
press "D".
-Please note that only empty directories may be deleted with the "D" mapping.
-Regular files are deleted with |delete()|, too.
+If your vim has 7.4 with patch#1107, then |g:netrw_localrmdir| no longer
+is used to remove directories; instead, vim's |delete()| is used with
+the "d" option. Please note that only empty directories may be deleted
+with the "D" mapping. Regular files are deleted with |delete()|, too.
The |g:netrw_rm_cmd|, |g:netrw_rmf_cmd|, and |g:netrw_rmdir_cmd| variables are
used to control the attempts to remove remote files and directories. The
@@ -1645,7 +1647,8 @@ to remove it again using the g:netrw_rmf_cmd variable. Its default value is:
|g:netrw_rmf_cmd|: ssh HOSTNAME rm -f
Related topics: |netrw-d|
-Associated setting variable: |g:netrw_rm_cmd| |g:netrw_ssh_cmd|
+Associated setting variable: |g:netrw_localrmdir| |g:netrw_rm_cmd|
+ |g:netrw_rmdir_cmd| |g:netrw_ssh_cmd|
*netrw-explore* *netrw-hexplore* *netrw-nexplore* *netrw-pexplore*
@@ -1688,11 +1691,7 @@ DIRECTORY EXPLORATION COMMANDS {{{2
to 2; edits will thus preferentially be made in window#2.
The [N] specifies a |g:netrw_winsize| just for the new :Lexplore
- window. That means that
- if [N] < 0 : use |N| columns for the Lexplore window
- if [N] = 0 : a normal split is made
- if [N] > 0 : use N% of the current window will be used for the
- new window
+ window.
Those who like this method often also like tree style displays;
see |g:netrw_liststyle|.
@@ -1976,7 +1975,7 @@ To use this function, simply assign its output to |g:netrw_list_hide| option. >
Example: let g:netrw_list_hide= netrw_gitignore#Hide('my_gitignore_file')
Function can take additional files with git-ignore patterns.
- Example: g:netrw_list_hide= netrw_gitignore#Hide() . '.*\.swp$'
+ Example: let g:netrw_list_hide= netrw_gitignore#Hide() .. '.*\.swp$'
Combining 'netrw_gitignore#Hide' with custom patterns.
<
@@ -2854,6 +2853,14 @@ your browsing preferences. (see also: |netrw-settings|)
=" /c move" Windows
Options for |g:netrw_localmovecmd|
+ *g:netrw_localrmdir* ="rmdir" Linux/Unix/MacOS/Cygwin
+ =expand("$COMSPEC") Windows
+ Remove directory command (rmdir)
+ This variable is only used if your vim is
+ earlier than 7.4 or if your vim doesn't
+ have patch#1107. Otherwise, |delete()|
+ is used with the "d" option.
+
*g:netrw_maxfilenamelen* =32 by default, selected so as to make long
listings fit on 80 column displays.
If your screen is wider, and you have file
@@ -3764,7 +3771,7 @@ Example: Clear netrw's marked file list via a mapping on gu >
Netrw uses several system level commands to do things (see
|g:netrw_localcopycmd|, |g:netrw_localmovecmd|,
- |g:netrw_mkdir_cmd|).
+ |g:netrw_localrmdir|, |g:netrw_mkdir_cmd|).
You may need to adjust the default commands for one or more of
these commands by setting them properly in your .vimrc. Another
@@ -3890,13 +3897,8 @@ netrw:
==============================================================================
12. History *netrw-history* {{{1
- v172: Sep 02, 2021 * (Bram Moolenaar) Changed "l:go" to "go"
- * (Bram Moolenaar) no need for "b" in
- netrw-safe guioptions
- Nov 15, 2021 * removed netrw_localrm and netrw_localrmdir
- references
- Aug 18, 2022 * (Miguel Barro) improving compatability with
- powershell
+ v172: Apr 22, 2023 * removed g:netrw_localrmdiropt
+ removed g:netrw_localrmdir
v171: Oct 09, 2020 * included code in s:NetrwOptionsSafe()
to allow |'bh'| to be set to delete when
rather than hide when g:netrw_fastbrowse
@@ -3981,8 +3983,10 @@ netrw:
Nov 09, 2016 * Broke apart the command from the options,
mostly for Windows. Introduced new netrw
settings: |g:netrw_localcopycmdopt|
- |g:netrw_localcopydircmdopt| |g:netrw_localmkdiropt|
- |g:netrw_localmovecmdopt| g:netrw_localrmdiropt
+ |g:netrw_localcopydircmdopt|
+ |g:netrw_localmkdiropt|
+ |g:netrw_localmovecmdopt|
+ g:netrw_localrmdiropt
Nov 21, 2016 * (mattn) provided a patch for preview; swapped
winwidth() with winheight()
Nov 22, 2016 * (glacambre) reported that files containing
@@ -4042,7 +4046,7 @@ netrw:
refreshes. However, inside a |:map-<expr>|,
tab and window changes are disallowed. Fixed.
(affects netrw's s:LocalBrowseRefresh())
- * g:netrw_localrmdir not used any more, but
+ * |g:netrw_localrmdir| not used any more, but
the relevant patch that causes |delete()| to
take over was #1107 (not #1109).
* |expand()| is now used on |g:netrw_home|;
@@ -4125,7 +4129,7 @@ netrw:
The "<nowait>" modifier has been included
with most of netrw's mappings to avoid that
delay.
- Jun 26, 2015 * |netrw-gn| mapping implemted
+ Jun 26, 2015 * |netrw-gn| mapping implemented
* :Ntree NotADir resulted in having
the tree listing expand in the error messages
window. Fixed.
@@ -4332,8 +4336,8 @@ netrw:
Dec 24, 2013 * (esquifit) asked that netrw allow the
/cygdrive prefix be a user-alterable
parameter.
- Jan 02, 2014 * Fixed a problem with netrw-based ballon
- evaluation (ie. netrw#NetrwBaloonHelp()
+ Jan 02, 2014 * Fixed a problem with netrw-based balloon
+ evaluation (ie. netrw#NetrwBalloonHelp()
not having been loaded error messages)
Jan 03, 2014 * Fixed a problem with tree listings
* New command installed: |:Ntree|
diff --git a/runtime/doc/pi_tar.txt b/runtime/doc/pi_tar.txt
index e664b98086..b104aef194 100644
--- a/runtime/doc/pi_tar.txt
+++ b/runtime/doc/pi_tar.txt
@@ -44,8 +44,8 @@ Copyright 2005-2017: *tar-copyright*
the file mentioned in the tarball. If the current directory is not
correct for that path, :TarDiff will fail to find the associated file.
- If the [filename] is given, that that filename (and path) will be used
- to specify the associated file.
+ If the [filename] is given, that filename (and path) will be used to
+ specify the associated file.
PREVENTING LOADING~
diff --git a/runtime/doc/provider.txt b/runtime/doc/provider.txt
index 432e6138fa..117997cec2 100644
--- a/runtime/doc/provider.txt
+++ b/runtime/doc/provider.txt
@@ -182,7 +182,7 @@ the "+" and/or "*" registers explicitly): >vim
See 'clipboard' for details and options.
*clipboard-tool*
-The presence of a working clipboard tool implicitly enables the '+' and '*'
+The presence of a working clipboard tool implicitly enables the '+' and "*"
registers. Nvim looks for these clipboard tools, in order of priority:
- |g:clipboard|
diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt
index 0b5757d720..7c06358be2 100644
--- a/runtime/doc/quickfix.txt
+++ b/runtime/doc/quickfix.txt
@@ -1615,7 +1615,7 @@ be escaped), meta symbols have to be written with leading '%':
%\ The single '\' character. Note that this has to be
escaped ("%\\") in ":set errorformat=" definitions.
%. The single '.' character.
- %# The single '*'(!) character.
+ %# The single "*"(!) character.
%^ The single '^' character. Note that this is not
useful, the pattern already matches start of line.
%$ The single '$' character. Note that this is not
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt
index 23030761dd..b6cb126c3b 100644
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -56,7 +56,7 @@ Using the underscore after `:d` avoids clobbering registers or the clipboard.
This also makes it faster.
Instead of the '/' which surrounds the {pattern}, you can use any other
-single byte character, but not an alphabetic character, '\', '"' or '|'.
+single byte character, but not an alphabetic character, '\', '"', '|' or '!'.
This is useful if you want to include a '/' in the search pattern or
replacement string.
@@ -336,6 +336,7 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
:scr[iptnames] List all sourced script names, in the order they were
first sourced. The number is used for the script ID
|<SID>|.
+ Also see `getscriptinfo()`.
:scr[iptnames][!] {scriptId} *:script*
Edit script {scriptId}. Although ":scriptnames name"
diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt
index 9f469767a2..b4c4debac7 100644
--- a/runtime/doc/sign.txt
+++ b/runtime/doc/sign.txt
@@ -468,7 +468,7 @@ sign_getplaced([{buf} [, {dict}]]) *sign_getplaced()*
id select sign with this identifier
lnum select signs placed in this line. For the use
of {lnum}, see |line()|.
- If {group} is '*', then signs in all the groups including the
+ If {group} is "*", then signs in all the groups including the
global group are returned. If {group} is not supplied or is an
empty string, then only signs in the global group are
returned. If no arguments are supplied, then signs in the
@@ -683,7 +683,7 @@ sign_unplace({group} [, {dict}]) *sign_unplace()*
is similar to the |:sign-unplace| command.
{group} is the sign group name. To use the global sign group,
- use an empty string. If {group} is set to '*', then all the
+ use an empty string. If {group} is set to "*", then all the
groups including the global group are used.
The signs in {group} are selected based on the entries in
{dict}. The following optional entries in {dict} are
@@ -735,7 +735,7 @@ sign_unplacelist({list}) *sign_unplacelist()*
the buffers.
group sign group name. If not specified or set to an
empty string, then the global sign group is
- used. If set to '*', then all the groups
+ used. If set to "*", then all the groups
including the global group are used.
id sign identifier. If not specified, then all
the signs in the specified group are removed.
diff --git a/runtime/doc/spell.txt b/runtime/doc/spell.txt
index d985093d9f..75e4767743 100644
--- a/runtime/doc/spell.txt
+++ b/runtime/doc/spell.txt
@@ -409,7 +409,7 @@ of the previous line "al." will be flagged as an error. And when you type
Use |CTRL-L| to redraw right away. "[s" will also stop at a word combination
with a line break.
-When encountering a line break Vim skips characters such as '*', '>' and '"',
+When encountering a line break Vim skips characters such as "*", '>' and '"',
so that comments in C, shell and Vim code can be spell checked.
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index 00a5e1c8ad..14f613d3fc 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -5020,7 +5020,7 @@ stop={term-list} *term-list* *highlight-stop*
highlighted area. This should undo the "start" argument.
Otherwise the screen will look messed up.
- {term-list} is a a string with escape sequences. This is any string of
+ {term-list} is a string with escape sequences. This is any string of
characters, except that it can't start with "t_" and blanks are not
allowed. The <> notation is recognized here, so you can use things
like "<Esc>" and "<Space>". Example:
@@ -5058,10 +5058,10 @@ ctermbg={color-nr} *ctermbg*
The number under "NR-16" is used for 16-color terminals ('t_Co'
greater than or equal to 16). The number under "NR-8" is used for
- 8-color terminals ('t_Co' less than 16). The '*' indicates that the
+ 8-color terminals ('t_Co' less than 16). The "*" indicates that the
bold attribute is set for ctermfg. In many 8-color terminals (e.g.,
"linux"), this causes the bright colors to appear. This doesn't work
- for background colors! Without the '*' the bold attribute is removed.
+ for background colors! Without the "*" the bold attribute is removed.
If you want to set the bold attribute in a different way, put a
"cterm=" argument AFTER the "ctermfg=" or "ctermbg=" argument. Or use
a number instead of a color name.
diff --git a/runtime/doc/testing.txt b/runtime/doc/testing.txt
index ef5e179c86..2c1c77a51d 100644
--- a/runtime/doc/testing.txt
+++ b/runtime/doc/testing.txt
@@ -54,13 +54,14 @@ assert_beeps({cmd}) *assert_beeps()*
assert_equal({expected}, {actual} [, {msg}])
When {expected} and {actual} are not equal an error message is
added to |v:errors| and 1 is returned. Otherwise zero is
- returned |assert-return|.
+ returned. |assert-return|
+ The error is in the form "Expected {expected} but got
+ {actual}". When {msg} is present it is prefixed to that.
+
There is no automatic conversion, the String "4" is different
from the Number 4. And the number 4 is different from the
Float 4.0. The value of 'ignorecase' is not used here, case
always matters.
- When {msg} is omitted an error in the form "Expected
- {expected} but got {actual}" is produced.
Example: >
assert_equal('foo', 'bar')
< Will result in a string to be added to |v:errors|:
@@ -134,11 +135,12 @@ assert_fails({cmd} [, {error} [, {msg} [, {lnum} [, {context}]]]])
assert_false({actual} [, {msg}]) *assert_false()*
When {actual} is not false an error message is added to
|v:errors|, like with |assert_equal()|.
+ The error is in the form "Expected False but got {actual}".
+ When {msg} is present it is prepended to that.
Also see |assert-return|.
+
A value is false when it is zero. When {actual} is not a
number the assert fails.
- When {msg} is omitted an error in the form
- "Expected False but got {actual}" is produced.
Can also be used as a |method|: >
GetResult()->assert_false()
@@ -147,14 +149,16 @@ assert_inrange({lower}, {upper}, {actual} [, {msg}]) *assert_inrange()*
This asserts number and |Float| values. When {actual} is lower
than {lower} or higher than {upper} an error message is added
to |v:errors|. Also see |assert-return|.
- When {msg} is omitted an error in the form
- "Expected range {lower} - {upper}, but got {actual}" is
- produced.
+ The error is in the form "Expected range {lower} - {upper},
+ but got {actual}". When {msg} is present it is prefixed to
+ that.
*assert_match()*
assert_match({pattern}, {actual} [, {msg}])
When {pattern} does not match {actual} an error message is
added to |v:errors|. Also see |assert-return|.
+ The error is in the form "Pattern {pattern} does not match
+ {actual}". When {msg} is present it is prefixed to that.
{pattern} is used as with |expr-=~|: The matching is always done
like 'magic' was set and 'cpoptions' is empty, no matter what
@@ -164,8 +168,6 @@ assert_match({pattern}, {actual} [, {msg}])
Use "^" and "$" to match with the start and end of the text.
Use both to match the whole text.
- When {msg} is omitted an error in the form
- "Pattern {pattern} does not match {actual}" is produced.
Example: >
assert_match('^f.*o$', 'foobar')
< Will result in a string to be added to |v:errors|:
@@ -215,8 +217,7 @@ assert_true({actual} [, {msg}]) *assert_true()*
Also see |assert-return|.
A value is |TRUE| when it is a non-zero number or |v:true|.
When {actual} is not a number or |v:true| the assert fails.
- When {msg} is omitted an error in the form "Expected True but
- got {actual}" is produced.
+ When {msg} is given it precedes the default message.
Can also be used as a |method|: >
GetResult()->assert_true()
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 0168b11499..64b4730eee 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -18,12 +18,13 @@ changes. This documentation may also not fully reflect the latest changes.
PARSER FILES *treesitter-parsers*
Parsers are the heart of tree-sitter. They are libraries that tree-sitter will
-search for in the `parser` runtime directory. By default, Nvim bundles only
-parsers for C, Lua, and Vimscript, but parsers can be installed manually or
-via a plugin like https://github.com/nvim-treesitter/nvim-treesitter.
-Parsers are searched for as `parser/{lang}.*` in any 'runtimepath' directory.
-If multiple parsers for the same language are found, the first one is used.
-(This typically implies the priority "user config > plugins > bundled".
+search for in the `parser` runtime directory. By default, Nvim bundles parsers
+for C, Lua, Vimscript, Vimdoc and Treesitter query files, but parsers can be
+installed manually or via a plugin like
+https://github.com/nvim-treesitter/nvim-treesitter. Parsers are searched for
+as `parser/{lang}.*` in any 'runtimepath' directory. If multiple parsers for
+the same language are found, the first one is used. (This typically implies
+the priority "user config > plugins > bundled".
A parser can also be loaded manually using a full path: >lua
vim.treesitter.language.add('python', { path = "/path/to/python.so" })
@@ -220,8 +221,7 @@ The following predicates are built in:
similar to `match?`
`contains?` *treesitter-predicate-contains?*
- Match a string against parts of the text corresponding to a node:
- >query
+ Match a string against parts of the text corresponding to a node: >query
((identifier) @foo (#contains? @foo "foo"))
((identifier) @foo-bar (#contains? @foo-bar "foo" "bar"))
<
@@ -233,6 +233,19 @@ The following predicates are built in:
This is the recommended way to check if the node matches one of many
keywords, as it has been optimized for this.
+ `has-ancestor?` *treesitter-predicate-has-ancestor?*
+ Match any of the given node types against all ancestors of a node: >query
+ ((identifier) @variable.builtin
+ (#any-of? @variable.builtin "begin" "end")
+ (#has-ancestor? @variable.builtin range_expression))
+<
+ `has-parent?` *treesitter-predicate-has-parent?*
+ Match any of the given node types against the direct ancestor of a
+ node: >query
+ (((field_expression
+ (field_identifier) @method)) @_parent
+ (#has-parent? @_parent template_method function_declarator))
+<
*lua-treesitter-not-predicate*
Each predicate has a `not-` prefixed predicate that is just the negation of
the predicate.
@@ -307,10 +320,10 @@ currently supported modeline alternatives:
Note: These modeline comments must be at the top of the query, but can be
repeated, for example, the following two modeline blocks are both valid:
>query
-
;; inherits: foo,bar
;; extends
-
+<
+>query
;; extends
;;
;; inherits: baz
@@ -907,11 +920,10 @@ Query:iter_captures({self}, {node}, {source}, {start}, {stop})
{source} is needed if the query contains predicates; then the caller must
ensure to use a freshly parsed tree consistent with the current text of
- the buffer (if relevant). {start_row} and {end_row} can be used to limit
- matches inside a row range (this is typically used with root node as the
- {node}, i.e., to get syntax highlight matches in the current viewport).
- When omitted, the {start} and {end} row values are used from the given
- node.
+ the buffer (if relevant). {start} and {stop} can be used to limit matches
+ inside a row range (this is typically used with root node as the {node},
+ i.e., to get syntax highlight matches in the current viewport). When
+ omitted, the {start} and {stop} row values are used from the given node.
The iterator returns three values: a numeric id identifying the capture,
the captured node, and metadata from any directives processing the match.
@@ -939,7 +951,7 @@ Query:iter_captures({self}, {node}, {source}, {start}, {stop})
metadata
*Query:iter_matches()*
-Query:iter_matches({self}, {node}, {source}, {start}, {stop})
+Query:iter_matches({self}, {node}, {source}, {start}, {stop}, {opts})
Iterates the matches of self on a given range.
Iterate over all matches within a {node}. The arguments are the same as
@@ -966,6 +978,11 @@ Query:iter_matches({self}, {node}, {source}, {start}, {stop})
• {source} (integer|string) Source buffer or string to search
• {start} (integer) Starting line for the search
• {stop} (integer) Stopping line for the search (end-exclusive)
+ • {opts} (table|nil) Options:
+ • max_start_depth (integer) if non-zero, sets the maximum
+ start depth for each match. This is used to prevent
+ traversing too deep into a tree. Requires treesitter >=
+ 0.20.9.
• {self}
Return: ~
@@ -1159,12 +1176,15 @@ LanguageTree:register_cbs({self}, {cbs}, {recursive})
• `on_bytes` : see |nvim_buf_attach()|, but this will be called after the parsers callback.
• `on_changedtree` : a callback that will be called
every time the tree has syntactical changes. It will
- only be passed one argument, which is a table of the
- ranges (as node ranges) that changed.
+ be passed two arguments: a table of the ranges (as
+ node ranges) that changed and the changed tree.
• `on_child_added` : emitted when a child is added to
the tree.
• `on_child_removed` : emitted when a child is removed
from the tree.
+ • `on_detach` : emitted when the buffer is detached, see
+ |nvim_buf_detach_event|. Takes one argument, the
+ number of the buffer.
• {recursive?} boolean Apply callbacks recursively for all children.
Any new children will also inherit the callbacks.
• {self}
diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt
index 4ff74714f3..c64c450aa1 100644
--- a/runtime/doc/ui.txt
+++ b/runtime/doc/ui.txt
@@ -336,7 +336,7 @@ numerical highlight ids to the actual attributes.
Highlights are always transmitted both for both the RGB format and as
terminal 256-color codes, as the `rgb_attr` and `cterm_attr` parameters
- respectively. The |ui-rgb| option has no effect effect anymore.
+ respectively. The |ui-rgb| option has no effect anymore.
Most external UIs will only need to store and use the `rgb_attr`
attributes.
@@ -352,7 +352,7 @@ numerical highlight ids to the actual attributes.
|ui-hlstate| extension explained below.
["hl_group_set", name, hl_id] ~
- The bulitin highlight group `name` was set to use the attributes `hl_id`
+ The built-in highlight group `name` was set to use the attributes `hl_id`
defined by a previous `hl_attr_define` call. This event is not needed
to render the grids which use attribute ids directly, but is useful
for a UI who want to render its own elements with consistent
@@ -710,7 +710,7 @@ For command-line 'wildmenu' UI events, activate |ui-popupmenu|.
to distinguish different command lines active at the same time. The
first invoked command line has level 1, the next recursively-invoked
prompt has level 2. A command line invoked from the |cmdline-window|
- has a higher level than than the edited command line.
+ has a higher level than the edited command line.
["cmdline_pos", pos, level] ~
Change the cursor position in the cmdline.
diff --git a/runtime/doc/usr_01.txt b/runtime/doc/usr_01.txt
index f0e2462fae..6b94806941 100644
--- a/runtime/doc/usr_01.txt
+++ b/runtime/doc/usr_01.txt
@@ -81,7 +81,7 @@ from within nvim. The tutorial will lead you from that point. Have fun!
==============================================================================
*01.4* Copyright *manual-copyright*
-The Vim user manual and reference manual are Copyright (c) 1988-2003 by Bram
+The Vim user manual and reference manual are Copyright (c) 1988 by Bram
Moolenaar. This material may be distributed only subject to the terms and
conditions set forth in the Open Publication License, v1.0 or later. The
latest version is presently available at:
diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt
index 0c6bd4f3a1..6ca486e8cf 100644
--- a/runtime/doc/visual.txt
+++ b/runtime/doc/visual.txt
@@ -398,7 +398,7 @@ selected text: >
(In the <> notation |<>|, when typing it you should type it literally; you
need to remove the 'B' flag from 'cpoptions')
-Note that special characters (like '.' and '*') will cause problems.
+Note that special characters (like '.' and "*") will cause problems.
Visual-block Examples *blockwise-examples*
With the following text, I will indicate the commands to produce the block and
diff --git a/runtime/ftplugin/luau.vim b/runtime/ftplugin/luau.vim
new file mode 100644
index 0000000000..458d0b05a9
--- /dev/null
+++ b/runtime/ftplugin/luau.vim
@@ -0,0 +1,14 @@
+" Vim filetype plugin file
+" Language: Luau
+" Maintainer: None yet
+" Last Change: 2023 Apr 30
+
+if exists("b:did_ftplugin")
+ finish
+endif
+
+" Luau is a superset of Lua
+runtime! ftplugin/lua.vim
+
+
+" vim: nowrap sw=2 sts=2 ts=8
diff --git a/runtime/ftplugin/usd.vim b/runtime/ftplugin/usd.vim
new file mode 100644
index 0000000000..c795ba591b
--- /dev/null
+++ b/runtime/ftplugin/usd.vim
@@ -0,0 +1,18 @@
+" Vim filetype plugin file
+" Language: Pixar Animation's Universal Scene Description format
+" Maintainer: Colin Kennedy <colinvfx@gmail.com>
+" Last Change: 2023 May 9
+
+if exists("b:did_ftplugin")
+ finish
+endif
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+let b:did_ftplugin = 1
+
+setlocal commentstring=#\ %s
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/runtime/indent/dts.vim b/runtime/indent/dts.vim
new file mode 100644
index 0000000000..e87f8153c7
--- /dev/null
+++ b/runtime/indent/dts.vim
@@ -0,0 +1,63 @@
+" Vim indent file
+" Language: Device Tree
+" Maintainer: Roland Hieber, Pengutronix <rhi@pengutronix.de>
+"
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal autoindent
+setlocal nosmartindent
+setlocal indentkeys=o,O,0},0<>>,!<Ctrl-F>
+setlocal indentexpr=GetDTSIndent()
+setlocal nolisp
+
+let b:undo_indent = 'setl autoindent< smartindent< indentkeys< indentexpr< lisp<'
+
+function GetDTSIndent()
+ let sw = shiftwidth()
+ let lnum = v:lnum
+ let line = getline(lnum)
+ let prevline = getline(prevnonblank(lnum-1))
+ let prevind = indent(prevnonblank(lnum-1))
+
+ if prevnonblank(lnum-1) < 1
+ return 0
+ endif
+
+ " Don't indent header and preprocessor directives
+ if line =~ '^\s*\(/dts-\|#\(include\|define\|undef\|warn\(ing\)\?\|error\|if\(n\?def\)\?\|else\|elif\|endif\)\)'
+ return 0
+
+ " Don't indent /node and &label blocks
+ elseif line =~ '^\s*[/&].\+{\s*$'
+ return 0
+
+ " Indent to matching bracket or remove one shiftwidth if line begins with } or >
+ elseif line =~ '^\s*[}>]'
+ " set cursor to closing bracket on current line
+ let col = matchend(line, '^\s*[>}]')
+ call cursor(lnum, col)
+
+ " determine bracket type, {} or <>
+ let pair = strpart('{}<>', stridx('}>', line[col-1]) * 2, 2)
+
+ " find matching bracket pair
+ let pairline = searchpair(pair[0], '', pair[1], 'bW')
+
+ if pairline > 0
+ return indent(pairline)
+ else
+ return prevind - sw
+ endif
+
+ " else, add one level of indent if line ends in { or < or = or ,
+ elseif prevline =~ '[{<=,]$'
+ return prevind + sw
+
+ else
+ return prevind
+ endif
+
+endfunction
diff --git a/runtime/indent/luau.vim b/runtime/indent/luau.vim
new file mode 100644
index 0000000000..69893f7399
--- /dev/null
+++ b/runtime/indent/luau.vim
@@ -0,0 +1,14 @@
+" Vim filetype indent file
+" Language: Luau
+" Maintainer: None yet
+" Last Change: 2023 Apr 30
+
+" Only load this indent file when no other was loaded.
+if exists("b:did_indent")
+ finish
+endif
+
+" Luau is a superset of Lua
+runtime! indent/lua.vim
+
+
diff --git a/runtime/indent/testdir/dts.in b/runtime/indent/testdir/dts.in
new file mode 100644
index 0000000000..64e56e9017
--- /dev/null
+++ b/runtime/indent/testdir/dts.in
@@ -0,0 +1,46 @@
+/* vim: set ft=dts noet sw=8 : */
+
+/* START_INDENT */
+/dts-v1/;
+#include <dt-bindings/pinctrl/pinctrl-imx6q.h>
+ #include "imx6qdl.dtsi"
+#include "imx6qdl-someboard.dtsi"
+
+ /delete-node/ &{/memory@10000000};
+
+ / {
+compatible = "some,board";
+/delete-node/ memory;
+
+ chosen {
+environment = &{usdhc4/partitions/partition@0};
+};
+}
+
+ &iomuxc {
+pinctrl-names = "default";
+pinctrl-0 = <&pinctrl_hog>;
+
+pinctrl_gpiohog: gpiohoggrp {
+fsl,pins = <
+MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x130b0
+MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x130b0
+>;
+};
+}
+
+&usdhc4 {
+partitions {
+compatible = "fixed-partitions";
+
+partition@0 {
+label = "environment";
+reg = <0x0 0xe0000>;
+};
+};
+};
+
+&{/aliases} {
+usb0 = &usb;
+};
+/* END_INDENT */
diff --git a/runtime/indent/testdir/dts.ok b/runtime/indent/testdir/dts.ok
new file mode 100644
index 0000000000..d249766fd4
--- /dev/null
+++ b/runtime/indent/testdir/dts.ok
@@ -0,0 +1,46 @@
+/* vim: set ft=dts noet sw=8 : */
+
+/* START_INDENT */
+/dts-v1/;
+#include <dt-bindings/pinctrl/pinctrl-imx6q.h>
+#include "imx6qdl.dtsi"
+#include "imx6qdl-someboard.dtsi"
+
+/delete-node/ &{/memory@10000000};
+
+/ {
+ compatible = "some,board";
+ /delete-node/ memory;
+
+ chosen {
+ environment = &{usdhc4/partitions/partition@0};
+ };
+}
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ pinctrl_gpiohog: gpiohoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x130b0
+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x130b0
+ >;
+ };
+}
+
+&usdhc4 {
+ partitions {
+ compatible = "fixed-partitions";
+
+ partition@0 {
+ label = "environment";
+ reg = <0x0 0xe0000>;
+ };
+ };
+};
+
+&{/aliases} {
+ usb0 = &usb;
+};
+/* END_INDENT */
diff --git a/runtime/lua/_vim9script.lua b/runtime/lua/_vim9script.lua
index 76e427b748..b983878637 100644
--- a/runtime/lua/_vim9script.lua
+++ b/runtime/lua/_vim9script.lua
@@ -312,7 +312,7 @@ vim9['fn'] = (function()
-- We do have vim9script ;) that's this plugin
['vim9script'] = true,
- -- Include some vim patches that are sometimes required by variuos vim9script plugins
+ -- Include some vim patches that are sometimes required by various vim9script plugins
-- that we implement via vim9jit
[ [[patch-8.2.2261]] ] = true,
[ [[patch-8.2.4257]] ] = true,
diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua
index 1158d80941..ac493bdc7f 100644
--- a/runtime/lua/man.lua
+++ b/runtime/lua/man.lua
@@ -583,7 +583,7 @@ local function get_paths(sect, name)
local mandirs = table.concat(vim.split(mandirs_raw, '[:\n]', { trimempty = true }), ',')
---@type string[]
- local paths = fn.globpath(mandirs, 'man?/' .. name .. '*.' .. sect .. '*', false, true)
+ local paths = fn.globpath(mandirs, 'man[^\\/]*/' .. name .. '*.' .. sect .. '*', false, true)
-- Prioritize the result from find_path as it obeys b:man_default_sects.
local first = M.find_path(sect, name)
@@ -739,7 +739,12 @@ function M.open_page(count, smods, args)
else
-- Combine the name and sect into a manpage reference so that all
-- verification/extraction can be kept in a single function.
- if tonumber(args[1]) then
+ if args[1]:match('^%d$') or args[1]:match('^%d%a') or args[1]:match('^%a$') then
+ -- NB: Valid sections are not only digits, but also:
+ -- - <digit><word> (see POSIX mans),
+ -- - and even <letter> and <word> (see, for example, by tcl/tk)
+ -- NB2: don't optimize to :match("^%d"), as it will match manpages like
+ -- 441toppm and others whose name starts with digit
local sect = args[1]
table.remove(args, 1)
local name = table.concat(args, ' ')
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index 20e813d77c..b26def5958 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -778,7 +778,7 @@ do
-- some bugs, so fake the two-step dance for now.
local matches
- --- Omnifunc for completing lua values from from the runtime lua interpreter,
+ --- Omnifunc for completing lua values from the runtime lua interpreter,
--- similar to the builtin completion for the `:lua` command.
---
--- Activate using `set omnifunc=v:lua.vim.lua_omnifunc` in a lua buffer.
diff --git a/runtime/lua/vim/_inspector.lua b/runtime/lua/vim/_inspector.lua
index 2ebb7a7efd..ecd39c35bc 100644
--- a/runtime/lua/vim/_inspector.lua
+++ b/runtime/lua/vim/_inspector.lua
@@ -90,7 +90,7 @@ function vim.inspect_pos(bufnr, row, col, filter)
nsmap[id] = name
end
- --- Convert an extmark tuple into a map-like table
+ --- Convert an extmark tuple into a table
--- @private
local function to_map(extmark)
extmark = {
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 5c799b23f2..1b04666161 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -579,6 +579,7 @@ local extension = {
['json-patch'] = 'json',
json5 = 'json5',
jsonc = 'jsonc',
+ jsonl = 'jsonl',
jsonnet = 'jsonnet',
libsonnet = 'jsonnet',
jsp = 'jsp',
@@ -997,7 +998,9 @@ local extension = {
spi = 'spyce',
spy = 'spyce',
tyc = 'sql',
- typ = 'sql',
+ typ = function(path, bufnr)
+ return require('vim.filetype.detect').typ(bufnr)
+ end,
pkb = 'sql',
tyb = 'sql',
pks = 'sql',
@@ -1078,6 +1081,8 @@ local extension = {
uit = 'uil',
uil = 'uil',
ungram = 'ungrammar',
+ usd = 'usd',
+ usda = 'usd',
sba = 'vb',
vb = 'vb',
dsm = 'vb',
diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua
index 74b01d569c..94106a3547 100644
--- a/runtime/lua/vim/filetype/detect.lua
+++ b/runtime/lua/vim/filetype/detect.lua
@@ -1322,6 +1322,28 @@ function M.txt(bufnr)
end
end
+function M.typ(bufnr)
+ if vim.g.filetype_typ then
+ return vim.g.filetype_typ
+ end
+
+ for _, line in ipairs(getlines(bufnr, 1, 200)) do
+ if
+ findany(line, {
+ '^CASE[%s]?=[%s]?SAME$',
+ '^CASE[%s]?=[%s]?LOWER$',
+ '^CASE[%s]?=[%s]?UPPER$',
+ '^CASE[%s]?=[%s]?OPPOSITE$',
+ '^TYPE%s',
+ })
+ then
+ return 'sql'
+ end
+ end
+
+ return 'typst'
+end
+
-- Determine if a .v file is Verilog, V, or Coq
function M.v(bufnr)
if vim.fn.did_filetype() ~= 0 then
diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua
index 2a51bde263..864ba495f1 100644
--- a/runtime/lua/vim/fs.lua
+++ b/runtime/lua/vim/fs.lua
@@ -72,8 +72,12 @@ function M.basename(file)
return file:match('[/\\]$') and '' or (file:match('[^\\/]*$'):gsub('\\', '/'))
end
----@private
-local function join_paths(...)
+--- Concatenate directories and/or file into a single path with normalization
+--- (e.g., `"foo/"` and `"bar"` get joined to `"foo/bar"`)
+---
+---@param ... string
+---@return string
+function M.joinpath(...)
return (table.concat({ ... }, '/'):gsub('//+', '/'))
end
@@ -116,14 +120,14 @@ function M.dir(path, opts)
local dirs = { { path, 1 } }
while #dirs > 0 do
local dir0, level = unpack(table.remove(dirs, 1))
- local dir = level == 1 and dir0 or join_paths(path, dir0)
+ local dir = level == 1 and dir0 or M.joinpath(path, dir0)
local fs = vim.loop.fs_scandir(M.normalize(dir))
while fs do
local name, t = vim.loop.fs_scandir_next(fs)
if not name then
break
end
- local f = level == 1 and name or join_paths(dir0, name)
+ local f = level == 1 and name or M.joinpath(dir0, name)
coroutine.yield(f, t)
if
opts.depth
@@ -230,7 +234,7 @@ function M.find(names, opts)
local t = {}
for name, type in M.dir(p) do
if (not opts.type or opts.type == type) and names(name, p) then
- table.insert(t, join_paths(p, name))
+ table.insert(t, M.joinpath(p, name))
end
end
return t
@@ -239,7 +243,7 @@ function M.find(names, opts)
test = function(p)
local t = {}
for _, name in ipairs(names) do
- local f = join_paths(p, name)
+ local f = M.joinpath(p, name)
local stat = vim.loop.fs_stat(f)
if stat and (not opts.type or opts.type == stat.type) then
t[#t + 1] = f
@@ -276,7 +280,7 @@ function M.find(names, opts)
end
for other, type_ in M.dir(dir) do
- local f = join_paths(dir, other)
+ local f = M.joinpath(dir, other)
if type(names) == 'function' then
if (not opts.type or opts.type == type_) and names(other, dir) then
if add(f) then
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 5c78bd7580..2e6ca7a0ac 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -8,12 +8,8 @@ local sync = require('vim.lsp.sync')
local semantic_tokens = require('vim.lsp.semantic_tokens')
local api = vim.api
-local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_buf_get_option, nvim_exec_autocmds =
- api.nvim_err_writeln,
- api.nvim_buf_get_lines,
- api.nvim_command,
- api.nvim_buf_get_option,
- api.nvim_exec_autocmds
+local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_exec_autocmds =
+ api.nvim_err_writeln, api.nvim_buf_get_lines, api.nvim_command, api.nvim_exec_autocmds
local uv = vim.loop
local tbl_isempty, tbl_extend = vim.tbl_isempty, vim.tbl_extend
local validate = vim.validate
@@ -137,7 +133,7 @@ local format_line_ending = {
---@param bufnr (number)
---@return string
local function buf_get_line_ending(bufnr)
- return format_line_ending[nvim_buf_get_option(bufnr, 'fileformat')] or '\n'
+ return format_line_ending[vim.bo[bufnr].fileformat] or '\n'
end
local client_index = 0
@@ -319,7 +315,7 @@ end
local function buf_get_full_text(bufnr)
local line_ending = buf_get_line_ending(bufnr)
local text = table.concat(nvim_buf_get_lines(bufnr, 0, -1, true), line_ending)
- if nvim_buf_get_option(bufnr, 'eol') then
+ if vim.bo[bufnr].eol then
text = text .. line_ending
end
return text
@@ -709,7 +705,7 @@ local function text_document_did_open_handler(bufnr, client)
if not api.nvim_buf_is_loaded(bufnr) then
return
end
- local filetype = nvim_buf_get_option(bufnr, 'filetype')
+ local filetype = vim.bo[bufnr].filetype
local params = {
textDocument = {
@@ -901,8 +897,8 @@ end
--- Field `cmd` in {config} is required.
---
---@param config (table) Configuration for the server:
---- - cmd: (table|string|fun(dispatchers: table):table) command string or
---- list treated like |jobstart()|. The command must launch the language server
+--- - cmd: (string[]|fun(dispatchers: table):table) command a list of
+--- strings treated like |jobstart()|. The command must launch the language server
--- process. `cmd` can also be a function that creates an RPC client.
--- The function receives a dispatchers table and must return a table with the
--- functions `request`, `notify`, `is_closing` and `terminate`
@@ -913,7 +909,7 @@ end
--- the `cmd` process. Not related to `root_dir`.
---
--- - cmd_env: (table) Environment flags to pass to the LSP on
---- spawn. Must be specified using a map-like table.
+--- spawn. Must be specified using a table.
--- Non-string values are coerced to string.
--- Example:
--- <pre>
@@ -2177,7 +2173,7 @@ end
---
--- Currently only supports a single client. This can be set via
--- `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` but will typically or in `on_attach`
---- via ``vim.api.nvim_buf_set_option(bufnr, 'formatexpr', 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})')``.
+--- via ``vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'``.
---
---@param opts table options for customizing the formatting expression which takes the
--- following optional keys:
diff --git a/runtime/lua/vim/lsp/_watchfiles.lua b/runtime/lua/vim/lsp/_watchfiles.lua
index 533a955925..cf2c57db1f 100644
--- a/runtime/lua/vim/lsp/_watchfiles.lua
+++ b/runtime/lua/vim/lsp/_watchfiles.lua
@@ -193,21 +193,27 @@ local to_lsp_change_type = {
function M.register(reg, ctx)
local client_id = ctx.client_id
local client = vim.lsp.get_client_by_id(client_id)
- if not client.workspace_folders then
+ if
+ -- Ill-behaved servers may not honor the client capability and try to register
+ -- anyway, so ignore requests when the user has opted out of the feature.
+ not client.config.capabilities.workspace.didChangeWatchedFiles.dynamicRegistration
+ or not client.workspace_folders
+ then
return
end
local watch_regs = {}
for _, w in ipairs(reg.registerOptions.watchers) do
+ local relative_pattern = false
local glob_patterns = {}
if type(w.globPattern) == 'string' then
for _, folder in ipairs(client.workspace_folders) do
table.insert(glob_patterns, { baseUri = folder.uri, pattern = w.globPattern })
end
else
+ relative_pattern = true
table.insert(glob_patterns, w.globPattern)
end
for _, glob_pattern in ipairs(glob_patterns) do
- local pattern = parse(glob_pattern.pattern)
local base_dir = nil
if type(glob_pattern.baseUri) == 'string' then
base_dir = glob_pattern.baseUri
@@ -216,9 +222,16 @@ function M.register(reg, ctx)
end
assert(base_dir, "couldn't identify root of watch")
base_dir = vim.uri_to_fname(base_dir)
+
local kind = w.kind
or protocol.WatchKind.Create + protocol.WatchKind.Change + protocol.WatchKind.Delete
+ local pattern = glob_pattern.pattern
+ if relative_pattern then
+ pattern = base_dir .. '/' .. pattern
+ end
+ pattern = parse(pattern)
+
table.insert(watch_regs, {
base_dir = base_dir,
pattern = pattern,
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 3d9011656f..a307dea673 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -31,7 +31,9 @@ end
--- ready.
---
---@returns `true` if server responds.
+---@deprecated
function M.server_ready()
+ vim.deprecate('vim.lsp.buf.server_ready', nil, '0.10.0')
return not not vim.lsp.buf_notify(0, 'window/progress', {})
end
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index 71bef43bc1..8e926c4644 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -454,7 +454,7 @@ function M.signature_help(_, result, ctx, config)
local client = vim.lsp.get_client_by_id(ctx.client_id)
local triggers =
vim.tbl_get(client.server_capabilities, 'signatureHelpProvider', 'triggerCharacters')
- local ft = api.nvim_buf_get_option(ctx.bufnr, 'filetype')
+ local ft = vim.bo[ctx.bufnr].filetype
local lines, hl = util.convert_signature_help_to_markdown_lines(result, ft, triggers)
lines = util.trim_empty_lines(lines)
if vim.tbl_isempty(lines) then
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 8274361f6d..9fffc845b1 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -401,7 +401,7 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding)
if not api.nvim_buf_is_loaded(bufnr) then
vim.fn.bufload(bufnr)
end
- api.nvim_buf_set_option(bufnr, 'buflisted', true)
+ vim.bo[bufnr].buflisted = true
-- Fix reversed range and indexing each text_edits
local index = 0
@@ -530,11 +530,7 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding)
-- Remove final line if needed
local fix_eol = has_eol_text_edit
- fix_eol = fix_eol
- and (
- api.nvim_buf_get_option(bufnr, 'eol')
- or (api.nvim_buf_get_option(bufnr, 'fixeol') and not api.nvim_buf_get_option(bufnr, 'binary'))
- )
+ fix_eol = fix_eol and (vim.bo[bufnr].eol or (vim.bo[bufnr].fixeol and not vim.bo[bufnr].binary))
fix_eol = fix_eol and get_line(bufnr, max - 1) == ''
if fix_eol then
api.nvim_buf_set_lines(bufnr, -2, -1, false, {})
@@ -1076,7 +1072,7 @@ function M.make_floating_popup_options(width, height, opts)
local wincol = opts.relative == 'mouse' and vim.fn.getmousepos().column or vim.fn.wincol()
- if wincol + width + (opts.offset_x or 0) <= api.nvim_get_option('columns') then
+ if wincol + width + (opts.offset_x or 0) <= vim.o.columns then
anchor = anchor .. 'W'
col = 0
else
@@ -1142,7 +1138,7 @@ function M.show_document(location, offset_encoding, opts)
or focus and api.nvim_get_current_win()
or create_window_without_focus()
- api.nvim_buf_set_option(bufnr, 'buflisted', true)
+ vim.bo[bufnr].buflisted = true
api.nvim_win_set_buf(win, bufnr)
if focus then
api.nvim_set_current_win(win)
@@ -1201,12 +1197,12 @@ function M.preview_location(location, opts)
end
local range = location.targetRange or location.range
local contents = api.nvim_buf_get_lines(bufnr, range.start.line, range['end'].line + 1, false)
- local syntax = api.nvim_buf_get_option(bufnr, 'syntax')
+ local syntax = vim.bo[bufnr].syntax
if syntax == '' then
-- When no syntax is set, we use filetype as fallback. This might not result
-- in a valid syntax definition. See also ft detection in stylize_markdown.
-- An empty syntax is more common now with TreeSitter, since TS disables syntax.
- syntax = api.nvim_buf_get_option(bufnr, 'filetype')
+ syntax = vim.bo[bufnr].filetype
end
opts = opts or {}
opts.focus_id = 'location'
@@ -1665,7 +1661,7 @@ function M.open_floating_preview(contents, syntax, opts)
contents = M.stylize_markdown(floating_bufnr, contents, opts)
else
if syntax then
- api.nvim_buf_set_option(floating_bufnr, 'syntax', syntax)
+ vim.bo[floating_bufnr].syntax = syntax
end
api.nvim_buf_set_lines(floating_bufnr, 0, -1, true, contents)
end
@@ -1681,16 +1677,16 @@ function M.open_floating_preview(contents, syntax, opts)
local float_option = M.make_floating_popup_options(width, height, opts)
local floating_winnr = api.nvim_open_win(floating_bufnr, false, float_option)
if do_stylize then
- api.nvim_win_set_option(floating_winnr, 'conceallevel', 2)
- api.nvim_win_set_option(floating_winnr, 'concealcursor', 'n')
+ vim.wo[floating_winnr].conceallevel = 2
+ vim.wo[floating_winnr].concealcursor = 'n'
end
-- disable folding
- api.nvim_win_set_option(floating_winnr, 'foldenable', false)
+ vim.wo[floating_winnr].foldenable = false
-- soft wrapping
- api.nvim_win_set_option(floating_winnr, 'wrap', opts.wrap)
+ vim.wo[floating_winnr].wrap = opts.wrap
- api.nvim_buf_set_option(floating_bufnr, 'modifiable', false)
- api.nvim_buf_set_option(floating_bufnr, 'bufhidden', 'wipe')
+ vim.bo[floating_bufnr].modifiable = false
+ vim.bo[floating_bufnr].bufhidden = 'wipe'
api.nvim_buf_set_keymap(
floating_bufnr,
'n',
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index a55deb1415..4f230c4412 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -361,7 +361,7 @@ local function tbl_extend(behavior, deep_extend, ...)
return ret
end
---- Merges two or more map-like tables.
+--- Merges two or more tables.
---
---@see |extend()|
---
@@ -369,13 +369,13 @@ end
--- - "error": raise an error
--- - "keep": use value from the leftmost map
--- - "force": use value from the rightmost map
----@param ... table Two or more map-like tables
+---@param ... table Two or more tables
---@return table Merged table
function vim.tbl_extend(behavior, ...)
return tbl_extend(behavior, false, ...)
end
---- Merges recursively two or more map-like tables.
+--- Merges recursively two or more tables.
---
---@see |vim.tbl_extend()|
---
@@ -385,7 +385,7 @@ end
--- - "error": raise an error
--- - "keep": use value from the leftmost map
--- - "force": use value from the rightmost map
----@param ... T2 Two or more map-like tables
+---@param ... T2 Two or more tables
---@return T1|T2 (table) Merged table
function vim.tbl_deep_extend(behavior, ...)
return tbl_extend(behavior, true, ...)
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index d1f5996768..12fbe1654f 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -136,16 +136,6 @@ function M.get_parser(bufnr, lang, opts)
return parsers[bufnr]
end
----@package
----@param bufnr (integer|nil) Buffer number
----@return boolean
-function M._has_parser(bufnr)
- if bufnr == nil or bufnr == 0 then
- bufnr = api.nvim_get_current_buf()
- end
- return parsers[bufnr] ~= nil
-end
-
--- Returns a string parser
---
---@param str string Text to parse
diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua
index f6425d7cb9..a8f8c7967e 100644
--- a/runtime/lua/vim/treesitter/_fold.lua
+++ b/runtime/lua/vim/treesitter/_fold.lua
@@ -301,7 +301,8 @@ function M.foldexpr(lnum)
lnum = lnum or vim.v.lnum
local bufnr = api.nvim_get_current_buf()
- if not ts._has_parser(bufnr) or not lnum then
+ local parser = vim.F.npcall(ts.get_parser, bufnr)
+ if not parser then
return '0'
end
@@ -309,7 +310,6 @@ function M.foldexpr(lnum)
foldinfos[bufnr] = FoldInfo.new()
get_folds_levels(bufnr, foldinfos[bufnr])
- local parser = ts.get_parser(bufnr)
parser:register_cbs({
on_changedtree = function(tree_changes)
on_changedtree(bufnr, foldinfos[bufnr], tree_changes)
diff --git a/runtime/lua/vim/treesitter/_meta.lua b/runtime/lua/vim/treesitter/_meta.lua
index 4d0f43d030..9ca4b560c6 100644
--- a/runtime/lua/vim/treesitter/_meta.lua
+++ b/runtime/lua/vim/treesitter/_meta.lua
@@ -31,17 +31,21 @@ local TSNode = {}
---@param query userdata
---@param captures true
----@param start integer
----@param end_ integer
+---@param start? integer
+---@param end_? integer
+---@param opts? table
---@return fun(): integer, TSNode, any
-function TSNode:_rawquery(query, captures, start, end_) end
+function TSNode:_rawquery(query, captures, start, end_, opts) end
---@param query userdata
---@param captures false
----@param start integer
----@param end_ integer
+---@param start? integer
+---@param end_? integer
+---@param opts? table
---@return fun(): string, any
-function TSNode:_rawquery(query, captures, start, end_) end
+function TSNode:_rawquery(query, captures, start, end_, opts) end
+
+---@alias TSLoggerCallback fun(logtype: 'parse'|'lex', msg: string)
---@class TSParser
---@field parse fun(self: TSParser, tree: TSTree?, source: integer|string, include_bytes: boolean?): TSTree, integer[]
@@ -50,6 +54,8 @@ function TSNode:_rawquery(query, captures, start, end_) end
---@field set_included_ranges fun(self: TSParser, ranges: Range6[])
---@field set_timeout fun(self: TSParser, timeout: integer)
---@field timeout fun(self: TSParser): integer
+---@field _set_logger fun(self: TSParser, lex: boolean, parse: boolean, cb: TSLoggerCallback)
+---@field _logger fun(self: TSParser): TSLoggerCallback
---@class TSTree
---@field root fun(self: TSTree): TSNode
diff --git a/runtime/lua/vim/treesitter/_range.lua b/runtime/lua/vim/treesitter/_range.lua
index f4db5016ac..35081c6400 100644
--- a/runtime/lua/vim/treesitter/_range.lua
+++ b/runtime/lua/vim/treesitter/_range.lua
@@ -143,6 +143,29 @@ function M.contains(r1, r2)
return true
end
+--- @param source integer|string
+--- @param index integer
+--- @return integer
+local function get_offset(source, index)
+ if index == 0 then
+ return 0
+ end
+
+ if type(source) == 'number' then
+ return api.nvim_buf_get_offset(source, index)
+ end
+
+ local byte = 0
+ local next_offset = source:gmatch('()\n')
+ local line = 1
+ while line <= index do
+ byte = next_offset() --[[@as integer]]
+ line = line + 1
+ end
+
+ return byte
+end
+
---@private
---@param source integer|string
---@param range Range
@@ -152,19 +175,10 @@ function M.add_bytes(source, range)
return range --[[@as Range6]]
end
- local start_row, start_col, end_row, end_col = range[1], range[2], range[3], range[4]
- local start_byte = 0
- local end_byte = 0
+ local start_row, start_col, end_row, end_col = M.unpack4(range)
-- TODO(vigoux): proper byte computation here, and account for EOL ?
- if type(source) == 'number' then
- -- Easy case, this is a buffer parser
- start_byte = api.nvim_buf_get_offset(source, start_row) + start_col
- end_byte = api.nvim_buf_get_offset(source, end_row) + end_col
- elseif type(source) == 'string' then
- -- string parser, single `\n` delimited string
- start_byte = vim.fn.byteidx(source, start_col)
- end_byte = vim.fn.byteidx(source, end_col)
- end
+ local start_byte = get_offset(source, start_row) + start_col
+ local end_byte = get_offset(source, end_row) + end_col
return { start_row, start_col, start_byte, end_row, end_col, end_byte }
end
diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua
index b616d4d70b..08c297c9ad 100644
--- a/runtime/lua/vim/treesitter/language.lua
+++ b/runtime/lua/vim/treesitter/language.lua
@@ -27,6 +27,11 @@ function M.get_lang(filetype)
if filetype == '' then
return
end
+ if ft_to_lang[filetype] then
+ return ft_to_lang[filetype]
+ end
+ -- support subfiletypes like html.glimmer
+ filetype = vim.split(filetype, '.', { plain = true })[1]
return ft_to_lang[filetype]
end
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index 1adf6759fa..6c780f33c4 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -31,8 +31,17 @@
--- shouldn't be done directly in the change callback anyway as they will be very frequent. Rather
--- a plugin that does any kind of analysis on a tree should use a timer to throttle too frequent
--- updates.
+---
+
+-- Debugging:
+--
+-- vim.g.__ts_debug levels:
+-- - 1. Messages from languagetree.lua
+-- - 2. Parse messages from treesitter
+-- - 2. Lex messages from treesitter
+--
+-- Log file can be found in stdpath('log')/treesitter.log
-local api = vim.api
local query = require('vim.treesitter.query')
local language = require('vim.treesitter.language')
local Range = require('vim.treesitter._range')
@@ -75,6 +84,8 @@ local TSCallbackNames = {
---@field private _source (integer|string) Buffer or string to parse
---@field private _trees TSTree[] Reference to parsed tree (one for each language)
---@field private _valid boolean|table<integer,boolean> If the parsed tree is valid
+---@field private _logger? fun(logtype: string, msg: string)
+---@field private _logfile? file*
local LanguageTree = {}
---@class LanguageTreeOpts
@@ -114,6 +125,10 @@ function LanguageTree.new(source, lang, opts)
_callbacks_rec = {},
}, LanguageTree)
+ if vim.g.__ts_debug and type(vim.g.__ts_debug) == 'number' then
+ self:_set_logger()
+ end
+
for _, name in pairs(TSCallbackNames) do
self._callbacks[name] = {}
self._callbacks_rec[name] = {}
@@ -122,6 +137,33 @@ function LanguageTree.new(source, lang, opts)
return self
end
+function LanguageTree:_set_logger()
+ local source = self:source()
+ source = type(source) == 'string' and 'text' or tostring(source)
+
+ local lang = self:lang()
+
+ local logfilename = vim.fs._join_paths(vim.fn.stdpath('log'), 'treesitter.log')
+
+ local logfile, openerr = io.open(logfilename, 'a+')
+
+ if not logfile or openerr then
+ error(string.format('Could not open file (%s) for logging: %s', logfilename, openerr))
+ return
+ end
+
+ self._logfile = logfile
+
+ self._logger = function(logtype, msg)
+ self._logfile:write(string.format('%s:%s:(%s) %s\n', source, lang, logtype, msg))
+ self._logfile:flush()
+ end
+
+ local log_lex = vim.g.__ts_debug >= 3
+ local log_parse = vim.g.__ts_debug >= 2
+ self._parser:_set_logger(log_lex, log_parse, self._logger)
+end
+
---@private
---Measure execution time of a function
---@generic R1, R2, R3
@@ -139,7 +181,11 @@ end
---@private
---@vararg any
function LanguageTree:_log(...)
- if vim.g.__ts_debug == nil then
+ if not self._logger then
+ return
+ end
+
+ if not vim.g.__ts_debug or vim.g.__ts_debug < 1 then
return
end
@@ -150,19 +196,17 @@ function LanguageTree:_log(...)
local info = debug.getinfo(2, 'nl')
local nregions = #self:included_regions()
- local prefix =
- string.format('%s:%d: [%s:%d] ', info.name, info.currentline, self:lang(), nregions)
+ local prefix = string.format('%s:%d: (#regions=%d) ', info.name, info.currentline, nregions)
- api.nvim_out_write(prefix)
+ local msg = { prefix }
for _, x in ipairs(args) do
if type(x) == 'string' then
- api.nvim_out_write(x)
+ msg[#msg + 1] = x
else
- api.nvim_out_write(vim.inspect(x, { newline = ' ', indent = '' }))
+ msg[#msg + 1] = vim.inspect(x, { newline = ' ', indent = '' })
end
- api.nvim_out_write(' ')
end
- api.nvim_out_write('\n')
+ self._logger('nvim', table.concat(msg, ' '))
end
--- Invalidates this parser and all its children
@@ -876,16 +920,23 @@ end
function LanguageTree:_on_detach(...)
self:invalidate(true)
self:_do_callback('detach', ...)
+ if self._logfile then
+ self._logger('nvim', 'detaching')
+ self._logger = nil
+ self._logfile:close()
+ end
end
--- Registers callbacks for the |LanguageTree|.
---@param cbs table An |nvim_buf_attach()|-like table argument with the following handlers:
--- - `on_bytes` : see |nvim_buf_attach()|, but this will be called _after_ the parsers callback.
--- - `on_changedtree` : a callback that will be called every time the tree has syntactical changes.
---- It will only be passed one argument, which is a table of the ranges (as node ranges) that
---- changed.
+--- It will be passed two arguments: a table of the ranges (as node ranges) that
+--- changed and the changed tree.
--- - `on_child_added` : emitted when a child is added to the tree.
--- - `on_child_removed` : emitted when a child is removed from the tree.
+--- - `on_detach` : emitted when the buffer is detached, see |nvim_buf_detach_event|.
+--- Takes one argument, the number of the buffer.
--- @param recursive? boolean Apply callbacks recursively for all children. Any new children will
--- also inherit the callbacks.
function LanguageTree:register_cbs(cbs, recursive)
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 93841bb31e..73b561c777 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -382,6 +382,39 @@ local predicate_handlers = {
return string_set[node_text]
end,
+
+ ['has-ancestor?'] = function(match, _, _, predicate)
+ local node = match[predicate[2]]
+ if not node then
+ return true
+ end
+
+ local ancestor_types = {}
+ for _, type in ipairs({ unpack(predicate, 3) }) do
+ ancestor_types[type] = true
+ end
+
+ node = node:parent()
+ while node do
+ if ancestor_types[node:type()] then
+ return true
+ end
+ node = node:parent()
+ end
+ return false
+ end,
+
+ ['has-parent?'] = function(match, _, _, predicate)
+ local node = match[predicate[2]]
+ if not node then
+ return true
+ end
+
+ if vim.list_contains({ unpack(predicate, 3) }, node:parent():type()) then
+ return true
+ end
+ return false
+ end,
}
-- As we provide lua-match? also expose vim-match?
@@ -609,10 +642,10 @@ end
---
--- {source} is needed if the query contains predicates; then the caller
--- must ensure to use a freshly parsed tree consistent with the current
---- text of the buffer (if relevant). {start_row} and {end_row} can be used to limit
+--- text of the buffer (if relevant). {start} and {stop} can be used to limit
--- matches inside a row range (this is typically used with root node
--- as the {node}, i.e., to get syntax highlight matches in the current
---- viewport). When omitted, the {start} and {end} row values are used from the given node.
+--- viewport). When omitted, the {start} and {stop} row values are used from the given node.
---
--- The iterator returns three values: a numeric id identifying the capture,
--- the captured node, and metadata from any directives processing the match.
@@ -686,16 +719,20 @@ end
---@param source (integer|string) Source buffer or string to search
---@param start integer Starting line for the search
---@param stop integer Stopping line for the search (end-exclusive)
+---@param opts table|nil Options:
+--- - max_start_depth (integer) if non-zero, sets the maximum start depth
+--- for each match. This is used to prevent traversing too deep into a tree.
+--- Requires treesitter >= 0.20.9.
---
---@return (fun(): integer, table<integer,TSNode>, table): pattern id, match, metadata
-function Query:iter_matches(node, source, start, stop)
+function Query:iter_matches(node, source, start, stop, opts)
if type(source) == 'number' and source == 0 then
source = api.nvim_get_current_buf()
end
start, stop = value_or_node_range(start, stop, node)
- local raw_iter = node:_rawquery(self.query, false, start, stop)
+ local raw_iter = node:_rawquery(self.query, false, start, stop, opts)
---@cast raw_iter fun(): string, any
local function iter()
local pattern, match = raw_iter()
diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua
index 3aacf3d4e0..ebe8f4e053 100644
--- a/runtime/lua/vim/version.lua
+++ b/runtime/lua/vim/version.lua
@@ -333,7 +333,7 @@ local function create_err_msg(v)
return string.format('invalid version: %s (%s)', tostring(v), type(v))
end
---- Parses and compares two version version objects (the result of |vim.version.parse()|, or
+--- Parses and compares two version objects (the result of |vim.version.parse()|, or
--- specified literally as a `{major, minor, patch}` tuple, e.g. `{1, 0, 3}`).
---
--- Example:
diff --git a/runtime/menu.vim b/runtime/menu.vim
index 2671bb51cb..d6f22b314c 100644
--- a/runtime/menu.vim
+++ b/runtime/menu.vim
@@ -2,7 +2,7 @@
" You can also use this as a start for your own set of menus.
"
" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2022 Nov 27
+" Last Change: 2023 May 03
" Note that ":an" (short for ":anoremenu") is often used to make a menu work
" in all modes and avoid side effects from mappings defined by the user.
@@ -599,7 +599,9 @@ func s:XxdBack()
exe ':%!' . g:xxdprogram . ' -r'
endif
set ft=
- doautocmd filetypedetect BufReadPost
+ if exists('#filetypedetect') && exists('#BufReadPost')
+ doautocmd filetypedetect BufReadPost
+ endif
let &mod = mod
endfun
diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
index 2c3f61c9d4..43c3d7541f 100644
--- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
+++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
@@ -1328,11 +1328,11 @@ function! s:OpenHoverPreview(lines, filetype) abort
\ })
if a:filetype isnot v:null
- call nvim_win_set_option(float_win_id, 'filetype', a:filetype)
+ call nvim_set_option_value('filetype', a:filetype, { 'win' : float_win_id })
endif
- call nvim_buf_set_option(buf, 'modified', v:false)
- call nvim_buf_set_option(buf, 'modifiable', v:false)
+ call nvim_set_option_value('modified', v:false, { 'buf' : buf })
+ call nvim_set_option_value('modifiable', v:false, { 'buf' : buf })
" Unlike preview window, :pclose does not close window. Instead, close
" hover window automatically when cursor is moved.
diff --git a/runtime/plugin/netrwPlugin.vim b/runtime/plugin/netrwPlugin.vim
index 431d9ad9c4..a347781e6f 100644
--- a/runtime/plugin/netrwPlugin.vim
+++ b/runtime/plugin/netrwPlugin.vim
@@ -20,7 +20,7 @@
if &cp || exists("g:loaded_netrwPlugin")
finish
endif
-let g:loaded_netrwPlugin = "v172"
+let g:loaded_netrwPlugin = "v173"
let s:keepcpo = &cpo
set cpo&vim
"DechoRemOn
diff --git a/runtime/queries/c/highlights.scm b/runtime/queries/c/highlights.scm
index dee70f9cc7..523a792403 100644
--- a/runtime/queries/c/highlights.scm
+++ b/runtime/queries/c/highlights.scm
@@ -117,12 +117,19 @@
(preproc_defined)
] @function.macro
-(field_identifier) @property
+(((field_expression
+ (field_identifier) @property)) @_parent
+ (#not-has-parent? @_parent template_method function_declarator call_expression))
+
+(field_designator) @property
+(((field_identifier) @property)
+ (#has-ancestor? @property field_declaration)
+ (#not-has-ancestor? @property function_declarator))
+
(statement_identifier) @label
[
(type_identifier)
- (sized_type_specifier)
(type_descriptor)
] @type
@@ -138,6 +145,8 @@
(primitive_type) @type.builtin
+(sized_type_specifier _ @type.builtin type: _?)
+
((identifier) @constant
(#lua-match? @constant "^[A-Z][A-Z0-9_]+$"))
(enumerator
@@ -163,6 +172,10 @@
field: (field_identifier) @function.call))
(function_declarator
declarator: (identifier) @function)
+(function_declarator
+ declarator: (parenthesized_declarator
+ (pointer_declarator
+ declarator: (field_identifier) @function)))
(preproc_function_def
name: (identifier) @function.macro)
diff --git a/runtime/queries/lua/highlights.scm b/runtime/queries/lua/highlights.scm
index 5fbf8a1833..537a171441 100644
--- a/runtime/queries/lua/highlights.scm
+++ b/runtime/queries/lua/highlights.scm
@@ -127,8 +127,14 @@
(identifier) @variable
+((identifier) @constant.builtin
+ (#eq? @constant.builtin "_VERSION"))
+
((identifier) @variable.builtin
- (#any-of? @variable.builtin "_G" "_VERSION" "debug" "io" "jit" "math" "os" "package" "self" "string" "table" "utf8"))
+ (#eq? @variable.builtin "self"))
+
+((identifier) @namespace.builtin
+ (#any-of? @namespace.builtin "_G" "debug" "io" "jit" "math" "os" "package" "string" "table" "utf8"))
((identifier) @keyword.coroutine
(#eq? @keyword.coroutine "coroutine"))
@@ -210,5 +216,7 @@
(string) @string @spell
+(escape_sequence) @string.escape
+
;; Error
(ERROR) @error
diff --git a/runtime/queries/lua/injections.scm b/runtime/queries/lua/injections.scm
index 1c7bdaf951..3fcebe83f3 100644
--- a/runtime/queries/lua/injections.scm
+++ b/runtime/queries/lua/injections.scm
@@ -13,6 +13,14 @@
(#set! injection.language "vim")
(#any-of? @_vimcmd_identifier "vim.cmd" "vim.api.nvim_command" "vim.api.nvim_exec2" "vim.api.nvim_cmd"))
+; vim.rcprequest(123, "nvim_exec_lua", "return vim.api.nvim_buf_get_lines(0, 0, -1, false)", false)
+((function_call
+ name: (_) @_vimcmd_identifier
+ arguments: (arguments . (_) . (string content: _ @_method) . (string content: _ @injection.content)))
+ (#set! injection.language "lua")
+ (#any-of? @_vimcmd_identifier "vim.rpcrequest" "vim.rpcnotify")
+ (#eq? @_method "nvim_exec_lua"))
+
((function_call
name: (_) @_vimcmd_identifier
arguments: (arguments (string content: _ @injection.content) .))
@@ -20,7 +28,7 @@
(#any-of? @_vimcmd_identifier "vim.treesitter.query.set" "vim.treesitter.query.parse"))
;; highlight string as query if starts with `;; query`
-((string ("string_content") @injection.content)
+(string content: _ @injection.content
(#set! injection.language "query")
(#lua-match? @injection.content "^%s*;+%s?query"))
diff --git a/runtime/queries/query/highlights.scm b/runtime/queries/query/highlights.scm
index ee31a7e7ef..f2d2ef6c7f 100644
--- a/runtime/queries/query/highlights.scm
+++ b/runtime/queries/query/highlights.scm
@@ -27,8 +27,8 @@
((parameters (identifier) @number)
(#match? @number "^[-+]?[0-9]+(.[0-9]+)?$"))
-((program . (comment) @include)
- (#match? @include "^;\ +inherits\ *:"))
+((program . (comment)* . (comment) @include)
+ (#lua-match? @include "^;+ *inherits *:"))
-((program . (comment) @preproc)
- (#match? @preproc "^; +extends"))
+((program . (comment)* . (comment) @preproc)
+ (#lua-match? @preproc "^;+ *extends"))
diff --git a/runtime/queries/vim/highlights.scm b/runtime/queries/vim/highlights.scm
index ce25b13b9f..09188ddb68 100644
--- a/runtime/queries/vim/highlights.scm
+++ b/runtime/queries/vim/highlights.scm
@@ -275,7 +275,7 @@
; Options
((set_value) @number
- (#match? @number "^[0-9]+(\.[0-9]+)?$"))
+ (#lua-match? @number "^[%d]+(%.[%d]+)?$"))
(inv_option "!" @operator)
(set_item "?" @operator)
diff --git a/runtime/queries/vimdoc/highlights.scm b/runtime/queries/vimdoc/highlights.scm
index c0d88301bc..e0dce49b2a 100644
--- a/runtime/queries/vimdoc/highlights.scm
+++ b/runtime/queries/vimdoc/highlights.scm
@@ -1,7 +1,7 @@
-(h1) @text.title
-(h2) @text.title
-(h3) @text.title
-(column_heading) @text.title
+(h1) @text.title.1
+(h2) @text.title.2
+(h3) @text.title.3
+(column_heading) @text.title.4
(column_heading
"~" @conceal (#set! conceal ""))
(tag
diff --git a/runtime/syntax/checkhealth.vim b/runtime/syntax/checkhealth.vim
index ea6555f005..2fd0aed601 100644
--- a/runtime/syntax/checkhealth.vim
+++ b/runtime/syntax/checkhealth.vim
@@ -12,7 +12,7 @@ unlet! b:current_syntax
syn case match
syn keyword DiagnosticError ERROR[:]
-syn keyword DiagnosticWarning WARNING[:]
+syn keyword DiagnosticWarn WARNING[:]
syn keyword DiagnosticOk OK[:]
syn match helpSectionDelim "^======*\n.*$"
syn match healthHeadingChar "=" conceal cchar=─ contained containedin=helpSectionDelim
diff --git a/runtime/syntax/dts.vim b/runtime/syntax/dts.vim
index be51ab5b10..bb7eff7be1 100644
--- a/runtime/syntax/dts.vim
+++ b/runtime/syntax/dts.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: dts/dtsi (device tree files)
" Maintainer: Daniel Mack <vim@zonque.org>
-" Last Change: 2022 Jun 14
+" Last Change: 2023 Apr 28
if exists("b:current_syntax")
finish
@@ -10,9 +10,10 @@ let b:current_syntax = 'dts'
syntax region dtsComment start="/\*" end="\*/"
syntax match dtsReference "&[[:alpha:][:digit:]_]\+"
+syntax match dtsReference "&{[[:alpha:][:digit:]@_/-]\+}"
syntax region dtsBinaryProperty start="\[" end="\]"
syntax match dtsStringProperty "\".*\""
-syntax match dtsKeyword "/.\{-1,\}/"
+syntax match dtsKeyword "/[[:alpha:][:digit:]-]\+/\([[:space:]]\|;\)"he=e-1
syntax match dtsLabel "^[[:space:]]*[[:alpha:][:digit:]_]\+:"
syntax match dtsNode /[[:alpha:][:digit:]-_]\+\(@[0-9a-fA-F]\+\|\)[[:space:]]*{/he=e-1
syntax region dtsCellProperty start="<" end=">" contains=dtsReference,dtsBinaryProperty,dtsStringProperty,dtsComment
diff --git a/runtime/syntax/luau.vim b/runtime/syntax/luau.vim
new file mode 100644
index 0000000000..59eccac100
--- /dev/null
+++ b/runtime/syntax/luau.vim
@@ -0,0 +1,15 @@
+" Vim syntax file
+" Language: Luau
+" Maintainer: None yet
+" Last Change: 2023 Apr 30
+
+if exists("b:current_syntax")
+ finish
+endif
+
+" Luau is a superset of lua
+runtime! syntax/lua.vim
+
+let b:current_syntax = "luau"
+
+" vim: nowrap sw=2 sts=2 ts=8 noet:
diff --git a/runtime/syntax/nasm.vim b/runtime/syntax/nasm.vim
index d763033225..0eb82fad10 100644
--- a/runtime/syntax/nasm.vim
+++ b/runtime/syntax/nasm.vim
@@ -3,8 +3,12 @@
" Maintainer: Andrii Sokolov <andriy145@gmail.com>
" Original Author: Manuel M.H. Stol <Manuel.Stol@allieddata.nl>
" Former Maintainer: Manuel M.H. Stol <Manuel.Stol@allieddata.nl>
-" Contributors: Leonard König <leonard.r.koenig@gmail.com> (C string highlighting), Peter Stanhope <dev.rptr@gmail.com> (Add missing 64-bit mode registers)
-" Last Change: 2017 Jan 23
+" Contributors:
+" Leonard König <leonard.r.koenig@gmail.com> (C string highlighting),
+" Peter Stanhope <dev.rptr@gmail.com> (Add missing 64-bit mode registers)
+" Frédéric Hamel <rederic.hamel123@gmail.com> (F16c support, partial AVX
+" support, other)
+" Last Change: 2022 May 3
" NASM Home: http://www.nasm.us/
@@ -277,7 +281,7 @@ syn match nasmInstrModifier "\<F\(ADD\|MUL\|\(DIV\|SUB\)R\=\)\s\+TO\>"lc=5,ms=
" NAsm directives
syn keyword nasmRepeat TIMES
syn keyword nasmDirective ALIGN[B] INCBIN EQU NOSPLIT SPLIT
-syn keyword nasmDirective ABSOLUTE BITS SECTION SEGMENT
+syn keyword nasmDirective ABSOLUTE BITS SECTION SEGMENT DEFAULT
syn keyword nasmDirective ENDSECTION ENDSEGMENT
syn keyword nasmDirective __SECT__
" Macro created standard directives: (requires %include)
@@ -309,7 +313,7 @@ syn match nasmStdInstruction "\<\(CMOV\|J\|SET\)\(N\=\([ABGL]E\=\|[CEOSZ]\)\|P
syn match nasmStdInstruction "\<POP\>"
syn keyword nasmStdInstruction AAA AAD AAM AAS ADC ADD AND
syn keyword nasmStdInstruction BOUND BSF BSR BSWAP BT[C] BTR BTS
-syn keyword nasmStdInstruction CALL CBW CDQ CLC CLD CMC CMP CMPSB CMPSD CMPSW CMPSQ
+syn keyword nasmStdInstruction CALL CBW CDQ CDQE CLC CLD CMC CMP CMPSB CMPSD CMPSW CMPSQ
syn keyword nasmStdInstruction CMPXCHG CMPXCHG8B CPUID CWD[E] CQO
syn keyword nasmStdInstruction DAA DAS DEC DIV ENTER
syn keyword nasmStdInstruction IDIV IMUL INC INT[O] IRET[D] IRETW IRETQ
@@ -319,6 +323,7 @@ syn keyword nasmStdInstruction LODSW LOOP[E] LOOPNE LOOPNZ LOOPZ LSS
syn keyword nasmStdInstruction MOVSB MOVSD MOVSW MOVSX MOVSQ MOVZX MUL NEG NOP NOT
syn keyword nasmStdInstruction OR POPA[D] POPAW POPF[D] POPFW POPFQ
syn keyword nasmStdInstruction PUSH[AD] PUSHAW PUSHF[D] PUSHFW PUSHFQ
+syn keyword nasmStdInstruction PAUSE
syn keyword nasmStdInstruction RCL RCR RETF RET[N] ROL ROR
syn keyword nasmStdInstruction SAHF SAL SAR SBB SCASB SCASD SCASW
syn keyword nasmStdInstruction SHL[D] SHR[D] STC STD STOSB STOSD STOSW STOSQ SUB
@@ -405,6 +410,62 @@ syn keyword nasmSseInstruction ORPS RCPPS RCPSS RSQRTPS RSQRTSS
syn keyword nasmSseInstruction SHUFPS SQRTPS SQRTSS STMXCSR SUBPS SUBSS
syn keyword nasmSseInstruction UCOMISS UNPCKHPS UNPCKLPS XORPS
+" F16c Instructions
+syn keyword nasmF16CInstruction VCVTPH2PS VCVTPS2PH
+
+" AVX Instructions
+syn keyword nasmAVXInstruction VCVTDQ2PD VCVTDQ2PS VCVTPD2DQ VCVTPD2P VCVTPD2PS
+syn keyword nasmAVXInstruction VCVTPS2DQ VCVTPS2PD
+syn keyword nasmAVXInstruction VCVTSD2SI VCVTSD2SS VCVTSI2SD VCVTSI2SS VCVTSS2SD VCVTSS2SI
+syn keyword nasmAVXInstruction VMAXPS VMAXSS VMINPS VMINSS VMOVAPS VMOVHLPS VMOVHPS
+syn keyword nasmAVXInstruction VMAXPD VMAXSD VMINPD VMINSD VMOVAPD VMOVHLPD VMOVHPD
+syn keyword nasmAVXInstruction VMOVLHPS VMOVLPS VMOVMSKPS VMOVNTPS VMOVSS VMOVUPS
+syn keyword nasmAVXInstruction VMULPS VMULSS VPXOR
+
+syn match nasmInstructnError "\<VP\a\{3}R\a\>"
+syn match nasmAVXInstruction "\<VP\(INS\|EXT\)R[BDQW]\>"
+
+syn keyword nasmAVXInstruction VORPS VPABSB VPABSD VPABSW
+syn keyword nasmAVXInstruction PACKSSDW VPACKSSWB VPACKUSDW VPACKUSWB VPADDD
+syn keyword nasmAVXInstruction PADDQ VPADDSB VPADDSW VPADDUSB VPADDUSW
+syn keyword nasmAVXInstruction PADDW VPALIGNR VPAND VPANDN VPAVGB
+syn keyword nasmAVXInstruction PAVGW VPBLENDD VPBLENDVB VPBLENDW VPBROADCASTB
+syn keyword nasmAVXInstruction PBROADCASTD VPBROADCASTQ VPBROADCASTW VPCLMULQDQ VPCMOV
+syn keyword nasmAVXInstruction PCMPEQB VPCMPEQD VPCMPEQQ VPCMPEQW VPCMPESTRI
+syn keyword nasmAVXInstruction PCMPESTRM VPCMPGTB VPCMPGTD VPCMPGTQ VPCMPGTW
+syn keyword nasmAVXInstruction PCMPISTRI VPCMPISTRM VPCOMB VPCOMD VPCOMQ
+syn keyword nasmAVXInstruction PCOMUB VPCOMUD VPCOMUQ VPCOMUW VPCOMW
+syn keyword nasmAVXInstruction PERM2FVPERM2IVPERMD VPERMIL2PD VPERMIL2PS VPERMILPD VPERMILPS
+syn keyword nasmAVXInstruction PERMPD VPERMPS VPERMQ VPEXTRB VPEXTRD
+syn keyword nasmAVXInstruction PEXTRQ VPEXTRW VPGATHERDD VPGATHERDQ VPGATHERQD
+syn keyword nasmAVXInstruction PGATHERQQ VPHADDBD VPHADDBQ VPHADDBW VPHADDD
+syn keyword nasmAVXInstruction PHADDDQ VPHADDSW VPHADDUBQ VPHADDUBW VPHADDUDQ
+syn keyword nasmAVXInstruction PHADDUWD VPHADDUWQ VPHADDW VPHADDWD VPHADDWQ
+syn keyword nasmAVXInstruction PHMINPOSUW VPHSUBBW VPHSUBD VPHSUBDQ VPHSUBSW
+syn keyword nasmAVXInstruction PHSUBW VPHSUBWD VPINSRB VPINSRD VPINSRQ
+syn keyword nasmAVXInstruction PINSRW VPMACSDD VPMACSDQH
+syn keyword nasmAVXInstruction VPMACSDQL VPMACSSDD VPMACSSDQL VPMACSSQH VPMACSSWD
+syn keyword nasmAVXInstruction VPMACSSWW VPMACSWD VPMACSWW VPMADCSSWD VPMADCSWD
+syn keyword nasmAVXInstruction VPMADDUBSW VPMADDWD VPMASKMOVD VPMASKMOVQ VPMAXSB
+syn keyword nasmAVXInstruction VPMAXSD VPMAXSW VPMAXUB VPMAXUD VPMAXUW
+syn keyword nasmAVXInstruction VPMINSB VPMINSD VPMINSW VPMINUB VPMINUD
+syn keyword nasmAVXInstruction VPMINUW VPMOVMSKB VPMOVSXBD VPMOVSXBQ VPMOVSXBW
+syn keyword nasmAVXInstruction VPMOVSXDQ VPMOVSXWD VPMOVSXWQ VPMOVZXBD VPMOVZXBQ
+syn keyword nasmAVXInstruction VPMOVZXBW VPMOVZXDQ VPMOVZXWD VPMOVZXWQ VPMULDQ
+syn keyword nasmAVXInstruction VPMULHRSW VPMULHUW VPMULHW VPMULLD VPMULLW
+syn keyword nasmAVXInstruction VPMULUDQ VPOR VPPERM VPROTB VPROTD
+syn keyword nasmAVXInstruction VPROTQ VPROTW VPSADBW VPSHAB VPSHAD
+syn keyword nasmAVXInstruction VPSHAQ VPSHAW VPSHLB VPSHLD VPSHLQ
+syn keyword nasmAVXInstruction VPSHLW VPSHUFB VPSHUFD VPSHUFHW VPSHUFLW
+syn keyword nasmAVXInstruction VPSIGNB VPSIGND VPSIGNW VPSLLD VPSLLDQ
+syn keyword nasmAVXInstruction VPSLLQ VPSLLVD VPSLLVQ VPSLLW VPSRAD
+syn keyword nasmAVXInstruction VPSRAVD VPSRAW VPSRLD VPSRLDQ VPSRLQ
+syn keyword nasmAVXInstruction VPSRLVD VPSRLVQ VPSRLW VPSUBB VPSUBD
+syn keyword nasmAVXInstruction VPSUBQ VPSUBSB VPSUBSW VPSUBUSB VPSUBUSW
+syn keyword nasmAVXInstruction VPSUBW VPTEST VPUNPCKHBW VPUNPCKHDQ VPUNPCKHQDQ
+syn keyword nasmAVXInstruction VPUNPCKHWD VPUNPCKLBW VPUNPCKLDQ VPUNPCKLQDQ VPUNPCKLWD
+syn keyword nasmAVXInstruction VPXOR VRCPPS
+
" Three Dimensional Now Packed Instructions: (requires 3DNow! unit)
syn keyword nasmNowInstruction FEMMS PAVGUSB PF2ID PFACC PFADD PFCMPEQ PFCMPGE
@@ -515,13 +576,14 @@ hi def link nasmDbgInstruction Debug
hi def link nasmFpuInstruction Statement
hi def link nasmMmxInstruction Statement
hi def link nasmSseInstruction Statement
+hi def link nasmF16cInstruction Statement
+hi def link nasmAVXInstruction Statement
hi def link nasmNowInstruction Statement
hi def link nasmAmdInstruction Special
hi def link nasmCrxInstruction Special
hi def link nasmUndInstruction Todo
hi def link nasmInstructnError Error
-
let b:current_syntax = "nasm"
" vim:ts=8 sw=4
diff --git a/runtime/syntax/xpm.vim b/runtime/syntax/xpm.vim
index be9f38723e..77d82403e9 100644
--- a/runtime/syntax/xpm.vim
+++ b/runtime/syntax/xpm.vim
@@ -1,10 +1,12 @@
" Vim syntax file
" Language: X Pixmap
" Maintainer: Ronald Schild <rs@scutum.de>
-" Last Change: 2021 Oct 04
-" Version: 5.4n.1
+" Last Change: 2023 May 11
+" Version: 5.4n.2
" Jemma Nelson added termguicolors support
" Dominique Pellé fixed spelling support
+" Christian J. Robinson fixed use of global variables, moved
+" loop into a function
" quit when a syntax file was already loaded
if exists("b:current_syntax")
@@ -21,108 +23,119 @@ syn region xpmPixelString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=@xpmCo
if has("gui_running") || has("termguicolors") && &termguicolors
-let color = ""
-let chars = ""
-let colors = 0
-let cpp = 0
-let n = 0
-let i = 1
+function s:CreateSyntax() abort
+ let color = ""
+ let chars = ""
+ let colors = 0
+ let cpp = 0
+ let n = 0
+ let lines = getline(1, '$')
-while i <= line("$") " scanning all lines
+ for line in lines " scanning all lines
- let s = matchstr(getline(i), '".\{-1,}"')
- if s != "" " does line contain a string?
+ let s = matchstr(line, '".\{-1,}"')
- if n == 0 " first string is the Values string
+ if s != "" " does line contain a string?
- " get the 3rd value: colors = number of colors
- let colors = substitute(s, '"\s*\d\+\s\+\d\+\s\+\(\d\+\).*"', '\1', '')
- " get the 4th value: cpp = number of character per pixel
- let cpp = substitute(s, '"\s*\d\+\s\+\d\+\s\+\d\+\s\+\(\d\+\).*"', '\1', '')
- if cpp =~ '[^0-9]'
- break " if cpp is not made of digits there must be something wrong
- endif
+ if n == 0 " first string is the Values string
- " Highlight the Values string as normal string (no pixel string).
- " Only when there is no slash, it would terminate the pattern.
- if s !~ '/'
- exe 'syn match xpmValues /' . s . '/'
- endif
- hi link xpmValues String
+ let values = split(s[1 : -2])
+
+ " Values string invalid, bail out
+ if len(values) != 4
+ return
+ endif
- let n = 1 " n = color index
+ " get the 3rd value: colors = number of colors
+ let colors = str2nr(values[2])
+ " get the 4th value: cpp = number of character per pixel
+ let cpp = str2nr(values[3])
- elseif n <= colors " string is a color specification
+ " these values must be positive, nonzero
+ if colors < 1 || cpp < 1
+ return
+ endif
+
+ " Highlight the Values string as normal string (no pixel string).
+ " Only when there is no slash, it would terminate the pattern.
+ if s !~ '/'
+ exe 'syn match xpmValues /' .. s .. '/'
+ endif
+ hi link xpmValues String
- " get chars = <cpp> length string representing the pixels
- " (first incl. the following whitespace)
- let chars = substitute(s, '"\(.\{'.cpp.'}\s\).*"', '\1', '')
+ let n = 1 " n = color index
- " now get color, first try 'c' key if any (color visual)
- let color = substitute(s, '".*\sc\s\+\(.\{-}\)\s*\(\(g4\=\|[ms]\)\s.*\)*\s*"', '\1', '')
- if color == s
- " no 'c' key, try 'g' key (grayscale with more than 4 levels)
- let color = substitute(s, '".*\sg\s\+\(.\{-}\)\s*\(\(g4\|[ms]\)\s.*\)*\s*"', '\1', '')
+ elseif n <= colors " string is a color specification
+
+ " get chars = <cpp> length string representing the pixels
+ " (first incl. the following whitespace)
+ let chars = substitute(s, '"\(.\{' .. cpp .. '}\s\).*"', '\1', '')
+
+ " now get color, first try 'c' key if any (color visual)
+ let color = substitute(s, '".*\sc\s\+\(.\{-}\)\s*\(\(g4\=\|[ms]\)\s.*\)*\s*"', '\1', '')
if color == s
- " next try: 'g4' key (4-level grayscale)
- let color = substitute(s, '".*\sg4\s\+\(.\{-}\)\s*\([ms]\s.*\)*\s*"', '\1', '')
+ " no 'c' key, try 'g' key (grayscale with more than 4 levels)
+ let color = substitute(s, '".*\sg\s\+\(.\{-}\)\s*\(\(g4\|[ms]\)\s.*\)*\s*"', '\1', '')
if color == s
- " finally try 'm' key (mono visual)
- let color = substitute(s, '".*\sm\s\+\(.\{-}\)\s*\(s\s.*\)*\s*"', '\1', '')
+ " next try: 'g4' key (4-level grayscale)
+ let color = substitute(s, '".*\sg4\s\+\(.\{-}\)\s*\([ms]\s.*\)*\s*"', '\1', '')
if color == s
- let color = ""
+ " finally try 'm' key (mono visual)
+ let color = substitute(s, '".*\sm\s\+\(.\{-}\)\s*\(s\s.*\)*\s*"', '\1', '')
+ if color == s
+ let color = ""
+ endif
endif
endif
endif
- endif
- " Vim cannot handle RGB codes with more than 6 hex digits
- if color =~ '#\x\{10,}$'
- let color = substitute(color, '\(\x\x\)\x\x', '\1', 'g')
- elseif color =~ '#\x\{7,}$'
- let color = substitute(color, '\(\x\x\)\x', '\1', 'g')
- " nor with 3 digits
- elseif color =~ '#\x\{3}$'
- let color = substitute(color, '\(\x\)\(\x\)\(\x\)', '0\10\20\3', '')
- endif
+ " Vim cannot handle RGB codes with more than 6 hex digits
+ if color =~ '#\x\{10,}$'
+ let color = substitute(color, '\(\x\x\)\x\x', '\1', 'g')
+ elseif color =~ '#\x\{7,}$'
+ let color = substitute(color, '\(\x\x\)\x', '\1', 'g')
+ " nor with 3 digits
+ elseif color =~ '#\x\{3}$'
+ let color = substitute(color, '\(\x\)\(\x\)\(\x\)', '0\10\20\3', '')
+ endif
- " escape meta characters in patterns
- let s = escape(s, '/\*^$.~[]')
- let chars = escape(chars, '/\*^$.~[]')
-
- " now create syntax items
- " highlight the color string as normal string (no pixel string)
- exe 'syn match xpmCol'.n.'Def /'.s.'/ contains=xpmCol'.n.'inDef'
- exe 'hi link xpmCol'.n.'Def String'
-
- " but highlight the first whitespace after chars in its color
- exe 'syn match xpmCol'.n.'inDef /"'.chars.'/hs=s+'.(cpp+1).' contained'
- exe 'hi link xpmCol'.n.'inDef xpmColor'.n
-
- " remove the following whitespace from chars
- let chars = substitute(chars, '.$', '', '')
-
- " and create the syntax item contained in the pixel strings
- exe 'syn match xpmColor'.n.' /'.chars.'/ contained'
- exe 'syn cluster xpmColors add=xpmColor'.n
-
- " if no color or color = "None" show background
- if color == "" || substitute(color, '.*', '\L&', '') == 'none'
- exe 'hi xpmColor'.n.' guifg=bg'
- exe 'hi xpmColor'.n.' guibg=NONE'
- elseif color !~ "'"
- exe 'hi xpmColor'.n." guifg='".color."'"
- exe 'hi xpmColor'.n." guibg='".color."'"
+ " escape meta characters in patterns
+ let s = escape(s, '/\*^$.~[] ')
+ let chars = escape(chars, '/\*^$.~[] ')
+
+ " now create syntax items
+ " highlight the color string as normal string (no pixel string)
+ exe 'syn match xpmCol' .. n .. 'Def /' .. s .. '/ contains=xpmCol' .. n .. 'inDef'
+ exe 'hi link xpmCol' .. n .. 'Def String'
+
+ " but highlight the first whitespace after chars in its color
+ exe 'syn match xpmCol' .. n .. 'inDef /"' .. chars .. '/hs=s+' .. (cpp + 1) .. ' contained'
+ exe 'hi link xpmCol' .. n .. 'inDef xpmColor' .. n
+
+ " remove the following whitespace from chars
+ let chars = substitute(chars, '.$', '', '')
+
+ " and create the syntax item contained in the pixel strings
+ exe 'syn match xpmColor' .. n .. ' /' .. chars .. '/ contained'
+ exe 'syn cluster xpmColors add=xpmColor' .. n
+
+ " if no color or color = "None" show background
+ if color == "" || substitute(color, '.*', '\L&', '') == 'none'
+ exe 'hi xpmColor' .. n .. ' guifg=bg'
+ exe 'hi xpmColor' .. n .. ' guibg=NONE'
+ elseif color !~ "'"
+ exe 'hi xpmColor' .. n .. " guifg='" .. color .. "'"
+ exe 'hi xpmColor' .. n .. " guibg='" .. color .. "'"
+ endif
+ let n += 1
+ else
+ break " no more color string
endif
- let n = n + 1
- else
- break " no more color string
endif
- endif
- let i = i + 1
-endwhile
+ endfor
+endfunction
-unlet color chars colors cpp n i s
+call s:CreateSyntax()
endif " has("gui_running") || has("termguicolors") && &termguicolors
diff --git a/scripts/bump_deps.lua b/scripts/bump_deps.lua
index 6a049d136a..076ad374cf 100755
--- a/scripts/bump_deps.lua
+++ b/scripts/bump_deps.lua
@@ -69,7 +69,7 @@ run({ 'mkdir', '-p', temp_dir })
local function get_dependency(dependency_name)
local dependency_table = {
- ['LuaJIT'] = {
+ ['luajit'] = {
repo = 'LuaJIT/LuaJIT',
symbol = 'LUAJIT',
},
@@ -77,7 +77,7 @@ local function get_dependency(dependency_name)
repo = 'libuv/libuv',
symbol = 'LIBUV',
},
- ['Luv'] = {
+ ['luv'] = {
repo = 'luvit/luv',
symbol = 'LUV',
},
@@ -85,6 +85,26 @@ local function get_dependency(dependency_name)
repo = 'tree-sitter/tree-sitter',
symbol = 'TREESITTER',
},
+ ['tree-sitter-c'] = {
+ repo = 'tree-sitter/tree-sitter-c',
+ symbol = 'TREESITTER_C',
+ },
+ ['tree-sitter-lua'] = {
+ repo = 'MunifTanjim/tree-sitter-lua',
+ symbol = 'TREESITTER_LUA',
+ },
+ ['tree-sitter-vim'] = {
+ repo = 'neovim/tree-sitter-vim',
+ symbol = 'TREESITTER_VIM',
+ },
+ ['tree-sitter-vimdoc'] = {
+ repo = 'neovim/tree-sitter-vimdoc',
+ symbol = 'TREESITTER_VIMDOC',
+ },
+ ['tree-sitter-query'] = {
+ repo = 'nvim-treesitter/tree-sitter-query',
+ symbol = 'TREESITTER_QUERY',
+ },
}
local dependency = dependency_table[dependency_name]
if dependency == nil then
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 385005a442..df0af72fdb 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -212,7 +212,7 @@ preprocess_patch() {
2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\<\%('"${na_src_testdir}"'\)\>@norm! d/\v(^diff)|%$ ' +w +q "$file"
# Remove testdir/test_*.vim files
- local na_src_testdir='balloon.*\|behave\.vim\|channel.*\|crypt\.vim\|cscope\.vim\|gui.*\|hardcopy\.vim\|job_fails\.vim\|json\.vim\|mzscheme\.vim\|netbeans.*\|paste\.vim\|popupwin.*\|restricted\.vim\|shortpathname\.vim\|tcl\.vim\|terminal.*\|xxd\.vim'
+ local na_src_testdir='balloon.*\|behave\.vim\|channel.*\|crypt\.vim\|cscope\.vim\|gui.*\|hardcopy\.vim\|job_fails\.vim\|json\.vim\|mzscheme\.vim\|netbeans.*\|paste\.vim\|popupwin.*\|python2\.vim\|pyx2\.vim\|restricted\.vim\|shortpathname\.vim\|tcl\.vim\|terminal.*\|xxd\.vim'
2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\<test_\%('"${na_src_testdir}"'\)\>@norm! d/\v(^diff)|%$ ' +w +q "$file"
# Remove version.c #7555
diff --git a/src/clint.py b/src/clint.py
index a6649763c2..ee2d0ecc3c 100755
--- a/src/clint.py
+++ b/src/clint.py
@@ -2244,6 +2244,7 @@ def CheckSpacing(filename, clean_lines, linenum, error):
r'(?<!\bkbtree_t)'
r'(?<!\bkbitr_t)'
r'(?<!\bPMap)'
+ r'(?<!\bSet)'
r'(?<!\bArrayOf)'
r'(?<!\bDictionaryOf)'
r'(?<!\bDict)'
diff --git a/src/klib/khash.h b/src/klib/khash.h
index 57a41f9c13..eb1714c471 100644
--- a/src/klib/khash.h
+++ b/src/klib/khash.h
@@ -185,41 +185,46 @@ typedef khint_t khiter_t;
#define __ac_HASH_UPPER 0.77
-#define __KHASH_TYPE(name, khkey_t, khval_t) \
+// This is only used for stack temporaries. Heap allocation is done with precise sizes.
+#define KHASH_MAX_VAL_SIZE 32
+
+#define __KHASH_TYPE(name, khkey_t) \
typedef struct { \
khint_t n_buckets, size, n_occupied, upper_bound; \
khint32_t *flags; \
khkey_t *keys; \
- khval_t *vals; \
+ char *vals_buf; \
} kh_##name##_t;
-#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \
+#define __KHASH_PROTOTYPES(name, khkey_t) \
extern kh_##name##_t *kh_init_##name(void); \
extern void kh_dealloc_##name(kh_##name##_t *h); \
extern void kh_destroy_##name(kh_##name##_t *h); \
extern void kh_clear_##name(kh_##name##_t *h); \
extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \
- extern void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
- extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \
+ extern void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets, size_t val_size); \
+ extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret, size_t val_size); \
extern void kh_del_##name(kh_##name##_t *h, khint_t x);
-#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, \
- __hash_equal) \
+#define kh_bval(h, x) (&(h)->vals_buf[val_size*(x)])
+#define kh_copyval(to, from) memcpy(to, from, val_size)
+
+#define __KHASH_IMPL(name, SCOPE, khkey_t, __hash_func, __hash_equal) \
SCOPE kh_##name##_t *kh_init_##name(void) \
- REAL_FATTR_UNUSED; \
+ REAL_FATTR_UNUSED; \
SCOPE kh_##name##_t *kh_init_##name(void) { \
return (kh_##name##_t *)kcalloc(1, sizeof(kh_##name##_t)); \
} \
SCOPE void kh_dealloc_##name(kh_##name##_t *h) \
- REAL_FATTR_UNUSED; \
+ REAL_FATTR_UNUSED; \
SCOPE void kh_dealloc_##name(kh_##name##_t *h) \
{ \
kfree(h->keys); \
kfree(h->flags); \
- kfree(h->vals); \
+ kfree(h->vals_buf); \
} \
SCOPE void kh_destroy_##name(kh_##name##_t *h) \
- REAL_FATTR_UNUSED; \
+ REAL_FATTR_UNUSED; \
SCOPE void kh_destroy_##name(kh_##name##_t *h) \
{ \
if (h) { \
@@ -228,7 +233,7 @@ typedef khint_t khiter_t;
} \
} \
SCOPE void kh_clear_##name(kh_##name##_t *h) \
- REAL_FATTR_UNUSED; \
+ REAL_FATTR_UNUSED; \
SCOPE void kh_clear_##name(kh_##name##_t *h) \
{ \
if (h && h->flags) { \
@@ -237,7 +242,7 @@ typedef khint_t khiter_t;
} \
} \
SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \
- REAL_FATTR_UNUSED; \
+ REAL_FATTR_UNUSED; \
SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \
{ \
if (h->n_buckets) { \
@@ -257,9 +262,9 @@ typedef khint_t khiter_t;
return 0; \
} \
} \
- SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \
- REAL_FATTR_UNUSED; \
- SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \
+ SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets, size_t val_size) \
+ REAL_FATTR_UNUSED; \
+ SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets, size_t val_size) \
{ /* This function uses 0.25*n_buckets bytes of working space instead of */ \
/* [sizeof(key_t+val_t)+.25]*n_buckets. */ \
khint32_t *new_flags = 0; \
@@ -280,23 +285,23 @@ typedef khint_t khiter_t;
if (h->n_buckets < new_n_buckets) { /* expand */ \
khkey_t *new_keys = (khkey_t *)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
h->keys = new_keys; \
- if (kh_is_map) { \
- khval_t *new_vals = \
- (khval_t *)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \
- h->vals = new_vals; \
+ if (val_size) { \
+ char *new_vals = krealloc( h->vals_buf, new_n_buckets * val_size); \
+ h->vals_buf = new_vals; \
} \
} /* otherwise shrink */ \
} \
} \
+ char cval[KHASH_MAX_VAL_SIZE]; \
+ char ctmp[KHASH_MAX_VAL_SIZE]; \
if (j) { /* rehashing is needed */ \
for (j = 0; j != h->n_buckets; ++j) { \
if (__ac_iseither(h->flags, j) == 0) { \
khkey_t key = h->keys[j]; \
- khval_t val; \
khint_t new_mask; \
new_mask = new_n_buckets - 1; \
- if (kh_is_map) { \
- val = h->vals[j]; \
+ if (val_size) { \
+ kh_copyval(cval, kh_bval(h, j)); \
} \
__ac_set_isdel_true(h->flags, j); \
/* kick-out process; sort of like in Cuckoo hashing */ \
@@ -315,17 +320,17 @@ typedef khint_t khiter_t;
h->keys[i] = key; \
key = tmp; \
} \
- if (kh_is_map) { \
- khval_t tmp = h->vals[i]; \
- h->vals[i] = val; \
- val = tmp; \
+ if (val_size) { \
+ kh_copyval(ctmp, kh_bval(h, i)); \
+ kh_copyval(kh_bval(h, i), cval); \
+ kh_copyval(cval, ctmp); \
} \
/* mark it as deleted in the old hash table */ \
__ac_set_isdel_true(h->flags, i); \
} else { /* write the element and jump out of the loop */ \
h->keys[i] = key; \
- if (kh_is_map) { \
- h->vals[i] = val; \
+ if (val_size) { \
+ kh_copyval(kh_bval(h, i), cval); \
} \
break; \
} \
@@ -335,9 +340,8 @@ typedef khint_t khiter_t;
if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \
h->keys = (khkey_t *)krealloc((void *)h->keys, \
new_n_buckets * sizeof(khkey_t)); \
- if (kh_is_map) { \
- h->vals = (khval_t *)krealloc((void *)h->vals, \
- new_n_buckets * sizeof(khval_t)); \
+ if (val_size) { \
+ h->vals_buf = krealloc((void *)h->vals_buf, new_n_buckets * val_size); \
} \
} \
kfree(h->flags); /* free the working space */ \
@@ -347,16 +351,16 @@ typedef khint_t khiter_t;
h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \
} \
} \
- SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \
- REAL_FATTR_UNUSED; \
- SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \
+ SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret, size_t val_size) \
+ REAL_FATTR_UNUSED; \
+ SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret, size_t val_size) \
{ \
khint_t x; \
if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \
if (h->n_buckets > (h->size << 1)) { \
- kh_resize_##name(h, h->n_buckets - 1); /* clear "deleted" elements */ \
+ kh_resize_##name(h, h->n_buckets - 1, val_size); /* clear "deleted" elements */ \
} else { \
- kh_resize_##name(h, h->n_buckets + 1); /* expand the hash table */ \
+ kh_resize_##name(h, h->n_buckets + 1, val_size); /* expand the hash table */ \
} \
} /* TODO: implement automatically shrinking; */ \
/* resize() already support shrinking */ \
@@ -407,7 +411,7 @@ typedef khint_t khiter_t;
return x; \
} \
SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \
- REAL_FATTR_UNUSED; \
+ REAL_FATTR_UNUSED; \
SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \
{ \
if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \
@@ -416,16 +420,16 @@ typedef khint_t khiter_t;
} \
}
-#define KHASH_DECLARE(name, khkey_t, khval_t) \
- __KHASH_TYPE(name, khkey_t, khval_t) \
- __KHASH_PROTOTYPES(name, khkey_t, khval_t)
+#define KHASH_DECLARE(khkey_t) \
+ __KHASH_TYPE(khkey_t, khkey_t) \
+ __KHASH_PROTOTYPES(khkey_t, khkey_t)
-#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
+#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, __hash_func, __hash_equal) \
__KHASH_TYPE(name, khkey_t, khval_t) \
- __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
+ __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, __hash_func, __hash_equal)
-#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
- KHASH_INIT2(name, static kh_inline, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
+#define KHASH_INIT(name, khkey_t, khval_t, __hash_func, __hash_equal) \
+ KHASH_INIT2(name, static kh_inline, khkey_t, khval_t, __hash_func, __hash_equal)
// --- BEGIN OF HASH FUNCTIONS ---
@@ -542,7 +546,7 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key)
the bucket has been deleted [int*]
@return Iterator to the inserted element [khint_t]
*/
-#define kh_put(name, h, k, r) kh_put_##name(h, k, r)
+#define kh_put(name, h, k, r, vs) kh_put_##name(h, k, r, vs)
/*! @function
@abstract Retrieve a key from the hash table.
@@ -584,12 +588,7 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key)
@return Value [type of values]
@discussion For hash sets, calling this results in segfault.
*/
-#define kh_val(h, x) ((h)->vals[x])
-
-/*! @function
- @abstract Alias of kh_val()
- */
-#define kh_value(h, x) ((h)->vals[x])
+#define kh_val(type, h, x) (*(type *)(&(h)->vals_buf[(x)*(sizeof (type))]))
/*! @function
@abstract Get the start iterator
@@ -626,13 +625,15 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key)
@param vvar Variable to which value will be assigned
@param code Block of code to execute
*/
-#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \
- for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
- if (!kh_exist(h, __i)) continue; \
- (kvar) = kh_key(h, __i); \
- (vvar) = kh_val(h, __i); \
- code; \
- } }
+#define kh_foreach(type, h, kvar, vvar, code) { \
+ khint_t __i; \
+ for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
+ if (!kh_exist(h,__i)) continue; \
+ (kvar) = kh_key(h,__i); \
+ (vvar) = kh_val(type, h,__i); \
+ code; \
+ } \
+}
/*! @function
@abstract Iterate over the values in the hash table
@@ -640,12 +641,14 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key)
@param vvar Variable to which value will be assigned
@param code Block of code to execute
*/
-#define kh_foreach_value(h, vvar, code) { khint_t __i; \
- for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
- if (!kh_exist(h, __i)) continue; \
- (vvar) = kh_val(h, __i); \
- code; \
- } }
+#define kh_foreach_value(type, h, vvar, code) { \
+ khint_t __i; \
+ for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
+ if (!kh_exist(h,__i)) continue; \
+ (vvar) = kh_val(type, h,__i); \
+ code; \
+ } \
+}
/*! @function
@abstract Iterate over the keys in the hash table
@@ -725,6 +728,6 @@ typedef const char *kh_cstr_t;
.upper_bound = 0, \
.flags = NULL, \
.keys = NULL, \
- .vals = NULL, \
+ .vals_buf = NULL, \
})
#endif // NVIM_LIB_KHASH_H
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index c9a46ecfa1..47f32abc07 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -9,7 +9,7 @@ if(TARGET libuv::uv_a)
else()
# Fall back to find module for older libuv versions that don't provide config file
find_package(Libuv 1.28.0 REQUIRED MODULE)
- target_include_directories(libuv SYSTEM BEFORE INTERFACE ${LIBUV_INCLUDE_DIRS})
+ target_include_directories(libuv SYSTEM BEFORE INTERFACE ${LIBUV_INCLUDE_DIR})
target_link_libraries(libuv INTERFACE ${LIBUV_LIBRARIES})
endif()
@@ -21,9 +21,9 @@ elseif(APPLE)
set_target_properties(nlua0 PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
endif()
-find_package(Libluv 1.43.0 REQUIRED)
-target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBLUV_INCLUDE_DIR})
-target_link_libraries(main_lib INTERFACE ${LIBLUV_LIBRARY})
+find_package(Luv 1.43.0 REQUIRED)
+target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LUV_INCLUDE_DIR})
+target_link_libraries(main_lib INTERFACE ${LUV_LIBRARY})
find_package(Iconv REQUIRED)
find_package(Lpeg REQUIRED)
@@ -61,11 +61,11 @@ if(PREFER_LUA)
find_package(Luajit)
else()
find_package(Luajit REQUIRED)
- target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LUAJIT_INCLUDE_DIRS})
- target_link_libraries(main_lib INTERFACE ${LUAJIT_LIBRARIES})
- target_include_directories(nlua0 SYSTEM BEFORE PUBLIC ${LUAJIT_INCLUDE_DIRS})
+ target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LUAJIT_INCLUDE_DIR})
+ target_link_libraries(main_lib INTERFACE ${LUAJIT_LIBRARY})
+ target_include_directories(nlua0 SYSTEM BEFORE PUBLIC ${LUAJIT_INCLUDE_DIR})
if(WIN32)
- target_link_libraries(nlua0 PUBLIC ${LUAJIT_LIBRARIES})
+ target_link_libraries(nlua0 PUBLIC ${LUAJIT_LIBRARY})
endif()
endif()
@@ -292,6 +292,7 @@ set(LUA_FILETYPE_MODULE_SOURCE ${PROJECT_SOURCE_DIR}/runtime/lua/vim/filetype.lu
set(LUA_INIT_PACKAGES_MODULE_SOURCE ${PROJECT_SOURCE_DIR}/runtime/lua/vim/_init_packages.lua)
set(LUA_KEYMAP_MODULE_SOURCE ${PROJECT_SOURCE_DIR}/runtime/lua/vim/keymap.lua)
set(CHAR_BLOB_GENERATOR ${GENERATOR_DIR}/gen_char_blob.lua)
+set(LUAJIT_RUNTIME_DIR ${DEPS_PREFIX}/share/luajit-2.1.0-beta3/jit)
glob_wrapper(UNICODE_FILES ${UNICODE_DIR}/*.txt)
glob_wrapper(API_HEADERS api/*.h)
@@ -798,6 +799,15 @@ install(DIRECTORY ${BINARY_LIB_DIR}
DESTINATION ${CMAKE_INSTALL_LIBDIR}/nvim/
USE_SOURCE_PERMISSIONS)
+if(NOT PREFER_LUA)
+ # install luajit runtime files if bundled
+ if(EXISTS ${LUAJIT_RUNTIME_DIR})
+ install(DIRECTORY ${LUAJIT_RUNTIME_DIR}
+ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/lua
+ USE_SOURCE_PERMISSIONS)
+ endif()
+endif()
+
add_library(libnvim STATIC EXCLUDE_FROM_ALL)
if(MSVC)
set(LIBNVIM_NAME libnvim)
@@ -826,6 +836,7 @@ if(ENABLE_ASAN_UBSAN)
-fsanitize=address
-fsanitize=undefined)
target_link_libraries(nvim PRIVATE -fsanitize=address -fsanitize=undefined)
+ target_compile_definitions(nvim PRIVATE ENABLE_ASAN_UBSAN)
elseif(ENABLE_MSAN)
message(STATUS "Enabling memory sanitizer for nvim.")
target_compile_options(nvim PRIVATE
@@ -877,18 +888,13 @@ add_glob_target(
EXCLUDE
tui/terminfo_defs.h)
-add_custom_target(uncrustify-version
- COMMAND ${CMAKE_COMMAND}
- -D UNCRUSTIFY_PRG=${UNCRUSTIFY_PRG}
- -D CONFIG_FILE=${PROJECT_SOURCE_DIR}/src/uncrustify.cfg
- -P ${PROJECT_SOURCE_DIR}/cmake/CheckUncrustifyVersion.cmake)
-
+set(UNCRUSTIFY_PRG ${DEPS_BIN_DIR}/uncrustify)
add_glob_target(
TARGET lintc-uncrustify
COMMAND ${UNCRUSTIFY_PRG}
FLAGS -c "${PROJECT_SOURCE_DIR}/src/uncrustify.cfg" -q --check
FILES ${LINT_NVIM_SOURCES})
-add_dependencies(lintc-uncrustify uncrustify-version)
+add_dependencies(lintc-uncrustify uncrustify)
add_custom_target(lintc)
add_dependencies(lintc lintc-clint lintc-uncrustify)
@@ -899,7 +905,7 @@ add_custom_target(formatc
-D LANG=c
-P ${PROJECT_SOURCE_DIR}/cmake/Format.cmake
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
-add_dependencies(formatc uncrustify-version)
+add_dependencies(formatc uncrustify)
add_custom_target(generated-sources DEPENDS
${NVIM_GENERATED_FOR_SOURCES}
diff --git a/src/nvim/README.md b/src/nvim/README.md
index cbd5daba4e..75155fb9c6 100644
--- a/src/nvim/README.md
+++ b/src/nvim/README.md
@@ -71,9 +71,8 @@ Create a directory to store logs:
Configure the sanitizer(s) via these environment variables:
# Change to detect_leaks=1 to detect memory leaks (slower, noisier).
- export ASAN_OPTIONS="detect_leaks=0:log_path=$HOME/logs/asan,handle_abort=1,handle_sigill=1"
+ export ASAN_OPTIONS="detect_leaks=0:log_path=$HOME/logs/asan"
# Show backtraces in the logs.
- export UBSAN_OPTIONS=print_stacktrace=1
export MSAN_OPTIONS="log_path=${HOME}/logs/msan"
export TSAN_OPTIONS="log_path=${HOME}/logs/tsan"
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index 6ecbff2606..14937cfd8f 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -293,17 +293,17 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
break;
case kCallbackFuncref:
case kCallbackPartial:
- PUT(autocmd_info, "callback", STRING_OBJ(cstr_as_string(callback_to_string(cb))));
+ PUT(autocmd_info, "callback", CSTR_AS_OBJ(callback_to_string(cb)));
break;
default:
abort();
}
} else {
- PUT(autocmd_info, "command", STRING_OBJ(cstr_as_string(xstrdup(ac->exec.callable.cmd))));
+ PUT(autocmd_info, "command", CSTR_TO_OBJ(ac->exec.callable.cmd));
}
- PUT(autocmd_info, "pattern", STRING_OBJ(cstr_to_string(ap->pat)));
- PUT(autocmd_info, "event", STRING_OBJ(cstr_to_string(event_nr2name(event))));
+ PUT(autocmd_info, "pattern", CSTR_TO_OBJ(ap->pat));
+ PUT(autocmd_info, "event", CSTR_TO_OBJ(event_nr2name(event)));
PUT(autocmd_info, "once", BOOLEAN_OBJ(ac->once));
if (ap->buflocal_nr) {
@@ -475,7 +475,7 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
}
if (patterns.size == 0) {
- ADD(patterns, STRING_OBJ(STATIC_CSTR_TO_STRING("*")));
+ ADD(patterns, STATIC_CSTR_TO_OBJ("*"));
}
VALIDATE_R((event_array.size > 0), "event", {
@@ -587,7 +587,7 @@ void nvim_clear_autocmds(Dict(clear_autocmds) *opts, Error *err)
// When we create the autocmds, we want to say that they are all matched, so that's *
// but when we clear them, we want to say that we didn't pass a pattern, so that's NUL
if (patterns.size == 0) {
- ADD(patterns, STRING_OBJ(STATIC_CSTR_TO_STRING("")));
+ ADD(patterns, STATIC_CSTR_TO_OBJ(""));
}
// If we didn't pass any events, that means clear all events.
@@ -763,7 +763,7 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
}
if (patterns.size == 0) {
- ADD(patterns, STRING_OBJ(STATIC_CSTR_TO_STRING("")));
+ ADD(patterns, STATIC_CSTR_TO_OBJ(""));
}
if (HAS_KEY(opts->data)) {
@@ -894,7 +894,7 @@ static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, Ob
}
snprintf((char *)pattern_buflocal, BUFLOCAL_PAT_LEN, "<buffer=%d>", (int)buf->handle);
- ADD(*patterns, STRING_OBJ(cstr_to_string(pattern_buflocal)));
+ ADD(*patterns, CSTR_TO_OBJ(pattern_buflocal));
}
return true;
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 10c684941c..82a62c3192 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -518,7 +518,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
{
MAXSIZE_TEMP_ARRAY(scratch, 1);
if (replacement.size == 0) {
- ADD_C(scratch, STRING_OBJ(STATIC_CSTR_AS_STRING("")));
+ ADD_C(scratch, STATIC_CSTR_AS_OBJ(""));
replacement = scratch;
}
diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c
index 3df80e3fed..6d715bcf46 100644
--- a/src/nvim/api/command.c
+++ b/src/nvim/api/command.c
@@ -245,7 +245,7 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err)
Dictionary filter = ARRAY_DICT_INIT;
PUT(filter, "pattern", cmdinfo.cmdmod.cmod_filter_pat
? CSTR_TO_OBJ(cmdinfo.cmdmod.cmod_filter_pat)
- : STRING_OBJ(STATIC_CSTR_TO_STRING("")));
+ : STATIC_CSTR_TO_OBJ(""));
PUT(filter, "force", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_filter_force));
PUT(mods, "filter", DICTIONARY_OBJ(filter));
@@ -438,7 +438,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
break;
}
- ADD(args, STRING_OBJ(cstr_as_string(data_str)));
+ ADD(args, CSTR_AS_OBJ(data_str));
}
bool argc_valid;
@@ -916,6 +916,7 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin
/// - args: (string) The args passed to the command, if any |<args>|
/// - fargs: (table) The args split by unescaped whitespace (when more than one
/// argument is allowed), if any |<f-args>|
+/// - nargs: (string) Number of arguments |:command-nargs|
/// - bang: (boolean) "true" if the command was executed with a ! modifier |<bang>|
/// - line1: (number) The starting line of the command range |<line1>|
/// - line2: (number) The final line of the command range |<line2>|
diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c
index 0ca505e7b2..a7e5b32d49 100644
--- a/src/nvim/api/deprecated.c
+++ b/src/nvim/api/deprecated.c
@@ -8,6 +8,7 @@
#include "nvim/api/buffer.h"
#include "nvim/api/deprecated.h"
#include "nvim/api/extmark.h"
+#include "nvim/api/options.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/validate.h"
@@ -522,3 +523,222 @@ Dictionary nvim_get_option_info(String name, Error *err)
{
return get_vimoption(name, OPT_GLOBAL, curbuf, curwin, err);
}
+
+/// Sets the global value of an option.
+///
+/// @deprecated
+/// @param channel_id
+/// @param name Option name
+/// @param value New option value
+/// @param[out] err Error details, if any
+void nvim_set_option(uint64_t channel_id, String name, Object value, Error *err)
+ FUNC_API_SINCE(1)
+{
+ set_option_to(channel_id, NULL, SREQ_GLOBAL, name, value, err);
+}
+
+/// Gets the global value of an option.
+///
+/// @deprecated
+/// @param name Option name
+/// @param[out] err Error details, if any
+/// @return Option value (global)
+Object nvim_get_option(String name, Arena *arena, Error *err)
+ FUNC_API_SINCE(1)
+{
+ return get_option_from(NULL, SREQ_GLOBAL, name, err);
+}
+
+/// Gets a buffer option value
+///
+/// @deprecated
+/// @param buffer Buffer handle, or 0 for current buffer
+/// @param name Option name
+/// @param[out] err Error details, if any
+/// @return Option value
+Object nvim_buf_get_option(Buffer buffer, String name, Arena *arena, Error *err)
+ FUNC_API_SINCE(1)
+{
+ buf_T *buf = find_buffer_by_handle(buffer, err);
+
+ if (!buf) {
+ return (Object)OBJECT_INIT;
+ }
+
+ return get_option_from(buf, SREQ_BUF, name, err);
+}
+
+/// Sets a buffer option value. Passing `nil` as value deletes the option (only
+/// works if there's a global fallback)
+///
+/// @deprecated
+/// @param channel_id
+/// @param buffer Buffer handle, or 0 for current buffer
+/// @param name Option name
+/// @param value Option value
+/// @param[out] err Error details, if any
+void nvim_buf_set_option(uint64_t channel_id, Buffer buffer, String name, Object value, Error *err)
+ FUNC_API_SINCE(1)
+{
+ buf_T *buf = find_buffer_by_handle(buffer, err);
+
+ if (!buf) {
+ return;
+ }
+
+ set_option_to(channel_id, buf, SREQ_BUF, name, value, err);
+}
+
+/// Gets a window option value
+///
+/// @deprecated
+/// @param window Window handle, or 0 for current window
+/// @param name Option name
+/// @param[out] err Error details, if any
+/// @return Option value
+Object nvim_win_get_option(Window window, String name, Arena *arena, Error *err)
+ FUNC_API_SINCE(1)
+{
+ win_T *win = find_window_by_handle(window, err);
+
+ if (!win) {
+ return (Object)OBJECT_INIT;
+ }
+
+ return get_option_from(win, SREQ_WIN, name, err);
+}
+
+/// Sets a window option value. Passing `nil` as value deletes the option (only
+/// works if there's a global fallback)
+///
+/// @deprecated
+/// @param channel_id
+/// @param window Window handle, or 0 for current window
+/// @param name Option name
+/// @param value Option value
+/// @param[out] err Error details, if any
+void nvim_win_set_option(uint64_t channel_id, Window window, String name, Object value, Error *err)
+ FUNC_API_SINCE(1)
+{
+ win_T *win = find_window_by_handle(window, err);
+
+ if (!win) {
+ return;
+ }
+
+ set_option_to(channel_id, win, SREQ_WIN, name, value, err);
+}
+
+/// Gets the value of a global or local (buffer, window) option.
+///
+/// @param from If `type` is `SREQ_WIN` or `SREQ_BUF`, this must be a pointer
+/// to the window or buffer.
+/// @param type One of `SREQ_GLOBAL`, `SREQ_WIN` or `SREQ_BUF`
+/// @param name The option name
+/// @param[out] err Details of an error that may have occurred
+/// @return the option value
+static Object get_option_from(void *from, int type, String name, Error *err)
+{
+ Object rv = OBJECT_INIT;
+
+ VALIDATE_S(name.size > 0, "option name", "<empty>", {
+ return rv;
+ });
+
+ // Return values
+ int64_t numval;
+ char *stringval = NULL;
+
+ int flags = get_option_value_strict(name.data, &numval, &stringval, type, from);
+ VALIDATE_S(flags != 0, "option name", name.data, {
+ return rv;
+ });
+
+ if (flags & SOPT_BOOL) {
+ rv.type = kObjectTypeBoolean;
+ rv.data.boolean = numval ? true : false;
+ } else if (flags & SOPT_NUM) {
+ rv.type = kObjectTypeInteger;
+ rv.data.integer = numval;
+ } else if (flags & SOPT_STRING) {
+ if (!stringval) {
+ api_set_error(err, kErrorTypeException, "Failed to get option '%s'", name.data);
+ return rv;
+ }
+ rv.type = kObjectTypeString;
+ rv.data.string.data = stringval;
+ rv.data.string.size = strlen(stringval);
+ } else {
+ api_set_error(err, kErrorTypeException, "Unknown type for option '%s'", name.data);
+ }
+
+ return rv;
+}
+
+/// Sets the value of a global or local (buffer, window) option.
+///
+/// @param to If `type` is `SREQ_WIN` or `SREQ_BUF`, this must be a pointer
+/// to the window or buffer.
+/// @param type One of `SREQ_GLOBAL`, `SREQ_WIN` or `SREQ_BUF`
+/// @param name The option name
+/// @param[out] err Details of an error that may have occurred
+static void set_option_to(uint64_t channel_id, void *to, int type, String name, Object value,
+ Error *err)
+{
+ VALIDATE_S(name.size > 0, "option name", "<empty>", {
+ return;
+ });
+
+ int flags = get_option_value_strict(name.data, NULL, NULL, type, to);
+ VALIDATE_S(flags != 0, "option name", name.data, {
+ return;
+ });
+
+ if (value.type == kObjectTypeNil) {
+ if (type == SREQ_GLOBAL) {
+ api_set_error(err, kErrorTypeException, "Cannot unset option '%s'", name.data);
+ return;
+ } else if (!(flags & SOPT_GLOBAL)) {
+ api_set_error(err, kErrorTypeException,
+ "Cannot unset option '%s' because it doesn't have a global value",
+ name.data);
+ return;
+ } else {
+ unset_global_local_option(name.data, to);
+ return;
+ }
+ }
+
+ long numval = 0;
+ char *stringval = NULL;
+
+ if (flags & SOPT_BOOL) {
+ VALIDATE(value.type == kObjectTypeBoolean, "Option '%s' value must be Boolean", name.data, {
+ return;
+ });
+ numval = value.data.boolean;
+ } else if (flags & SOPT_NUM) {
+ VALIDATE(value.type == kObjectTypeInteger, "Option '%s' value must be Integer", name.data, {
+ return;
+ });
+ VALIDATE((value.data.integer <= INT_MAX && value.data.integer >= INT_MIN),
+ "Option '%s' value is out of range", name.data, {
+ return;
+ });
+ numval = (int)value.data.integer;
+ } else {
+ VALIDATE(value.type == kObjectTypeString, "Option '%s' value must be String", name.data, {
+ return;
+ });
+ stringval = value.data.string.data;
+ }
+
+ // For global-win-local options -> setlocal
+ // For win-local options -> setglobal and setlocal (opt_flags == 0)
+ const int opt_flags = (type == SREQ_WIN && !(flags & SOPT_GLOBAL)) ? 0 :
+ (type == SREQ_GLOBAL) ? OPT_GLOBAL : OPT_LOCAL;
+
+ WITH_SCRIPT_CONTEXT(channel_id, {
+ access_option_value_for(name.data, &numval, &stringval, opt_flags, type, to, false, err);
+ });
+}
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index 87232a8a93..299413e510 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -33,12 +33,10 @@
void api_extmark_free_all_mem(void)
{
String name;
- handle_T id;
- map_foreach(&namespace_ids, name, id, {
- (void)id;
+ map_foreach_key(&namespace_ids, name, {
xfree(name.data);
})
- map_destroy(String, handle_T)(&namespace_ids);
+ map_destroy(String, &namespace_ids);
}
/// Creates a new namespace or gets an existing one. \*namespace\*
@@ -77,7 +75,7 @@ Dictionary nvim_get_namespaces(void)
String name;
handle_T id;
- map_foreach(&namespace_ids, name, id, {
+ map_foreach(handle_T, &namespace_ids, name, id, {
PUT(retval, name.data, INTEGER_OBJ(id));
})
@@ -88,7 +86,7 @@ const char *describe_ns(NS ns_id)
{
String name;
handle_T id;
- map_foreach(&namespace_ids, name, id, {
+ map_foreach(handle_T, &namespace_ids, name, id, {
if ((NS)id == ns_id && name.size) {
return name.data;
}
@@ -108,7 +106,7 @@ bool ns_initialized(uint32_t ns)
static Object hl_group_name(int hl_id, bool hl_name)
{
if (hl_name) {
- return STRING_OBJ(cstr_to_string(syn_id2name(hl_id)));
+ return CSTR_TO_OBJ(syn_id2name(hl_id));
} else {
return INTEGER_OBJ(hl_id);
}
@@ -142,7 +140,7 @@ static Array extmark_to_array(const ExtmarkInfo *extmark, bool id, bool add_dict
PUT(dict, "hl_eol", BOOLEAN_OBJ(decor->hl_eol));
}
if (decor->hl_mode) {
- PUT(dict, "hl_mode", STRING_OBJ(cstr_to_string(hl_mode_str[decor->hl_mode])));
+ PUT(dict, "hl_mode", CSTR_TO_OBJ(hl_mode_str[decor->hl_mode]));
}
if (kv_size(decor->virt_text)) {
@@ -150,7 +148,7 @@ static Array extmark_to_array(const ExtmarkInfo *extmark, bool id, bool add_dict
for (size_t i = 0; i < decor->virt_text.size; i++) {
Array chunk = ARRAY_DICT_INIT;
VirtTextChunk *vtc = &decor->virt_text.items[i];
- ADD(chunk, STRING_OBJ(cstr_to_string(vtc->text)));
+ ADD(chunk, CSTR_TO_OBJ(vtc->text));
if (vtc->hl_id > 0) {
ADD(chunk, hl_group_name(vtc->hl_id, hl_name));
}
@@ -162,7 +160,7 @@ static Array extmark_to_array(const ExtmarkInfo *extmark, bool id, bool add_dict
PUT(dict, "virt_text_win_col", INTEGER_OBJ(decor->col));
}
PUT(dict, "virt_text_pos",
- STRING_OBJ(cstr_to_string(virt_text_pos_str[decor->virt_text_pos])));
+ CSTR_TO_OBJ(virt_text_pos_str[decor->virt_text_pos]));
}
if (decor->ui_watched) {
@@ -179,7 +177,7 @@ static Array extmark_to_array(const ExtmarkInfo *extmark, bool id, bool add_dict
for (size_t j = 0; j < vt->size; j++) {
Array chunk = ARRAY_DICT_INIT;
VirtTextChunk *vtc = &vt->items[j];
- ADD(chunk, STRING_OBJ(cstr_to_string(vtc->text)));
+ ADD(chunk, CSTR_TO_OBJ(vtc->text));
if (vtc->hl_id > 0) {
ADD(chunk, hl_group_name(vtc->hl_id, hl_name));
}
@@ -193,7 +191,7 @@ static Array extmark_to_array(const ExtmarkInfo *extmark, bool id, bool add_dict
}
if (decor->sign_text) {
- PUT(dict, "sign_text", STRING_OBJ(cstr_to_string(decor->sign_text)));
+ PUT(dict, "sign_text", CSTR_TO_OBJ(decor->sign_text));
}
// uncrustify:off
@@ -479,6 +477,8 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// - "overlay": display over the specified column, without
/// shifting the underlying text.
/// - "right_align": display right aligned in the window.
+/// - "inline": display at the specified column, and
+/// shift the buffer text to the right as needed
/// - virt_text_win_col : position the virtual text at a fixed
/// window column (starting from the first
/// text column)
@@ -697,6 +697,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
decor.virt_text_pos = kVTOverlay;
} else if (strequal("right_align", str.data)) {
decor.virt_text_pos = kVTRightAlign;
+ } else if (strequal("inline", str.data)) {
+ decor.virt_text_pos = kVTInline;
} else {
VALIDATE_S(false, "virt_text_pos", "", {
goto error;
diff --git a/src/nvim/api/extmark.h b/src/nvim/api/extmark.h
index a6586e3031..3c979fa4f6 100644
--- a/src/nvim/api/extmark.h
+++ b/src/nvim/api/extmark.h
@@ -6,7 +6,6 @@
#include "nvim/decoration.h"
#include "nvim/macros.h"
#include "nvim/map.h"
-#include "nvim/map_defs.h"
#include "nvim/types.h"
EXTERN Map(String, handle_T) namespace_ids INIT(= MAP_INIT);
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c
index 2d1b170d2d..e18312a6dc 100644
--- a/src/nvim/api/options.c
+++ b/src/nvim/api/options.c
@@ -188,7 +188,7 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err)
switch (result) {
case gov_string:
- rv = STRING_OBJ(cstr_as_string(stringval));
+ rv = CSTR_AS_OBJ(stringval);
break;
case gov_number:
rv = INTEGER_OBJ(numval);
@@ -341,218 +341,6 @@ Dictionary nvim_get_option_info2(String name, Dict(option) *opts, Error *err)
return get_vimoption(name, scope, buf, win, err);
}
-/// Sets the global value of an option.
-///
-/// @param channel_id
-/// @param name Option name
-/// @param value New option value
-/// @param[out] err Error details, if any
-void nvim_set_option(uint64_t channel_id, String name, Object value, Error *err)
- FUNC_API_SINCE(1)
-{
- set_option_to(channel_id, NULL, SREQ_GLOBAL, name, value, err);
-}
-
-/// Gets the global value of an option.
-///
-/// @param name Option name
-/// @param[out] err Error details, if any
-/// @return Option value (global)
-Object nvim_get_option(String name, Arena *arena, Error *err)
- FUNC_API_SINCE(1)
-{
- return get_option_from(NULL, SREQ_GLOBAL, name, err);
-}
-
-/// Gets a buffer option value
-///
-/// @param buffer Buffer handle, or 0 for current buffer
-/// @param name Option name
-/// @param[out] err Error details, if any
-/// @return Option value
-Object nvim_buf_get_option(Buffer buffer, String name, Arena *arena, Error *err)
- FUNC_API_SINCE(1)
-{
- buf_T *buf = find_buffer_by_handle(buffer, err);
-
- if (!buf) {
- return (Object)OBJECT_INIT;
- }
-
- return get_option_from(buf, SREQ_BUF, name, err);
-}
-
-/// Sets a buffer option value. Passing `nil` as value deletes the option (only
-/// works if there's a global fallback)
-///
-/// @param channel_id
-/// @param buffer Buffer handle, or 0 for current buffer
-/// @param name Option name
-/// @param value Option value
-/// @param[out] err Error details, if any
-void nvim_buf_set_option(uint64_t channel_id, Buffer buffer, String name, Object value, Error *err)
- FUNC_API_SINCE(1)
-{
- buf_T *buf = find_buffer_by_handle(buffer, err);
-
- if (!buf) {
- return;
- }
-
- set_option_to(channel_id, buf, SREQ_BUF, name, value, err);
-}
-
-/// Gets a window option value
-///
-/// @param window Window handle, or 0 for current window
-/// @param name Option name
-/// @param[out] err Error details, if any
-/// @return Option value
-Object nvim_win_get_option(Window window, String name, Arena *arena, Error *err)
- FUNC_API_SINCE(1)
-{
- win_T *win = find_window_by_handle(window, err);
-
- if (!win) {
- return (Object)OBJECT_INIT;
- }
-
- return get_option_from(win, SREQ_WIN, name, err);
-}
-
-/// Sets a window option value. Passing `nil` as value deletes the option (only
-/// works if there's a global fallback)
-///
-/// @param channel_id
-/// @param window Window handle, or 0 for current window
-/// @param name Option name
-/// @param value Option value
-/// @param[out] err Error details, if any
-void nvim_win_set_option(uint64_t channel_id, Window window, String name, Object value, Error *err)
- FUNC_API_SINCE(1)
-{
- win_T *win = find_window_by_handle(window, err);
-
- if (!win) {
- return;
- }
-
- set_option_to(channel_id, win, SREQ_WIN, name, value, err);
-}
-
-/// Gets the value of a global or local (buffer, window) option.
-///
-/// @param from If `type` is `SREQ_WIN` or `SREQ_BUF`, this must be a pointer
-/// to the window or buffer.
-/// @param type One of `SREQ_GLOBAL`, `SREQ_WIN` or `SREQ_BUF`
-/// @param name The option name
-/// @param[out] err Details of an error that may have occurred
-/// @return the option value
-static Object get_option_from(void *from, int type, String name, Error *err)
-{
- Object rv = OBJECT_INIT;
-
- VALIDATE_S(name.size > 0, "option name", "<empty>", {
- return rv;
- });
-
- // Return values
- int64_t numval;
- char *stringval = NULL;
-
- int flags = get_option_value_strict(name.data, &numval, &stringval, type, from);
- VALIDATE_S(flags != 0, "option name", name.data, {
- return rv;
- });
-
- if (flags & SOPT_BOOL) {
- rv.type = kObjectTypeBoolean;
- rv.data.boolean = numval ? true : false;
- } else if (flags & SOPT_NUM) {
- rv.type = kObjectTypeInteger;
- rv.data.integer = numval;
- } else if (flags & SOPT_STRING) {
- if (!stringval) {
- api_set_error(err, kErrorTypeException, "Failed to get option '%s'", name.data);
- return rv;
- }
- rv.type = kObjectTypeString;
- rv.data.string.data = stringval;
- rv.data.string.size = strlen(stringval);
- } else {
- api_set_error(err, kErrorTypeException, "Unknown type for option '%s'", name.data);
- }
-
- return rv;
-}
-
-/// Sets the value of a global or local (buffer, window) option.
-///
-/// @param to If `type` is `SREQ_WIN` or `SREQ_BUF`, this must be a pointer
-/// to the window or buffer.
-/// @param type One of `SREQ_GLOBAL`, `SREQ_WIN` or `SREQ_BUF`
-/// @param name The option name
-/// @param[out] err Details of an error that may have occurred
-void set_option_to(uint64_t channel_id, void *to, int type, String name, Object value, Error *err)
-{
- VALIDATE_S(name.size > 0, "option name", "<empty>", {
- return;
- });
-
- int flags = get_option_value_strict(name.data, NULL, NULL, type, to);
- VALIDATE_S(flags != 0, "option name", name.data, {
- return;
- });
-
- if (value.type == kObjectTypeNil) {
- if (type == SREQ_GLOBAL) {
- api_set_error(err, kErrorTypeException, "Cannot unset option '%s'", name.data);
- return;
- } else if (!(flags & SOPT_GLOBAL)) {
- api_set_error(err, kErrorTypeException,
- "Cannot unset option '%s' because it doesn't have a global value",
- name.data);
- return;
- } else {
- unset_global_local_option(name.data, to);
- return;
- }
- }
-
- long numval = 0;
- char *stringval = NULL;
-
- if (flags & SOPT_BOOL) {
- VALIDATE(value.type == kObjectTypeBoolean, "Option '%s' value must be Boolean", name.data, {
- return;
- });
- numval = value.data.boolean;
- } else if (flags & SOPT_NUM) {
- VALIDATE(value.type == kObjectTypeInteger, "Option '%s' value must be Integer", name.data, {
- return;
- });
- VALIDATE((value.data.integer <= INT_MAX && value.data.integer >= INT_MIN),
- "Option '%s' value is out of range", name.data, {
- return;
- });
- numval = (int)value.data.integer;
- } else {
- VALIDATE(value.type == kObjectTypeString, "Option '%s' value must be String", name.data, {
- return;
- });
- stringval = value.data.string.data;
- }
-
- // For global-win-local options -> setlocal
- // For win-local options -> setglobal and setlocal (opt_flags == 0)
- const int opt_flags = (type == SREQ_WIN && !(flags & SOPT_GLOBAL)) ? 0 :
- (type == SREQ_GLOBAL) ? OPT_GLOBAL : OPT_LOCAL;
-
- WITH_SCRIPT_CONTEXT(channel_id, {
- access_option_value_for(name.data, &numval, &stringval, opt_flags, type, to, false, err);
- });
-}
-
static getoption_T access_option_value(char *key, long *numval, char **stringval, int opt_flags,
bool get, Error *err)
{
@@ -571,8 +359,8 @@ static getoption_T access_option_value(char *key, long *numval, char **stringval
}
}
-static getoption_T access_option_value_for(char *key, long *numval, char **stringval, int opt_flags,
- int opt_type, void *from, bool get, Error *err)
+getoption_T access_option_value_for(char *key, long *numval, char **stringval, int opt_flags,
+ int opt_type, void *from, bool get, Error *err)
{
bool need_switch = false;
switchwin_T switchwin;
diff --git a/src/nvim/api/options.h b/src/nvim/api/options.h
index 869826e443..7be72d3708 100644
--- a/src/nvim/api/options.h
+++ b/src/nvim/api/options.h
@@ -3,6 +3,7 @@
#include "nvim/api/keysets.h"
#include "nvim/api/private/defs.h"
+#include "nvim/option.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/options.h.generated.h"
diff --git a/src/nvim/api/private/converter.h b/src/nvim/api/private/converter.h
index 80ee640295..28ae71983b 100644
--- a/src/nvim/api/private/converter.h
+++ b/src/nvim/api/private/converter.h
@@ -2,7 +2,7 @@
#define NVIM_API_PRIVATE_CONVERTER_H
#include "nvim/api/private/defs.h"
-#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/private/converter.h.generated.h"
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 02060a8950..2544809553 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -660,10 +660,10 @@ static void init_ui_event_metadata(Dictionary *metadata)
msgpack_unpacked_destroy(&unpacked);
PUT(*metadata, "ui_events", ui_events);
Array ui_options = ARRAY_DICT_INIT;
- ADD(ui_options, STRING_OBJ(cstr_to_string("rgb")));
+ ADD(ui_options, CSTR_TO_OBJ("rgb"));
for (UIExtension i = 0; i < kUIExtCount; i++) {
if (ui_ext_names[i][0] != '_') {
- ADD(ui_options, STRING_OBJ(cstr_to_string(ui_ext_names[i])));
+ ADD(ui_options, CSTR_TO_OBJ(ui_ext_names[i]));
}
}
PUT(*metadata, "ui_options", ARRAY_OBJ(ui_options));
@@ -692,17 +692,17 @@ static void init_type_metadata(Dictionary *metadata)
Dictionary buffer_metadata = ARRAY_DICT_INIT;
PUT(buffer_metadata, "id",
INTEGER_OBJ(kObjectTypeBuffer - EXT_OBJECT_TYPE_SHIFT));
- PUT(buffer_metadata, "prefix", STRING_OBJ(cstr_to_string("nvim_buf_")));
+ PUT(buffer_metadata, "prefix", CSTR_TO_OBJ("nvim_buf_"));
Dictionary window_metadata = ARRAY_DICT_INIT;
PUT(window_metadata, "id",
INTEGER_OBJ(kObjectTypeWindow - EXT_OBJECT_TYPE_SHIFT));
- PUT(window_metadata, "prefix", STRING_OBJ(cstr_to_string("nvim_win_")));
+ PUT(window_metadata, "prefix", CSTR_TO_OBJ("nvim_win_"));
Dictionary tabpage_metadata = ARRAY_DICT_INIT;
PUT(tabpage_metadata, "id",
INTEGER_OBJ(kObjectTypeTabpage - EXT_OBJECT_TYPE_SHIFT));
- PUT(tabpage_metadata, "prefix", STRING_OBJ(cstr_to_string("nvim_tabpage_")));
+ PUT(tabpage_metadata, "prefix", CSTR_TO_OBJ("nvim_tabpage_"));
PUT(types, "Buffer", DICTIONARY_OBJ(buffer_metadata));
PUT(types, "Window", DICTIONARY_OBJ(window_metadata));
diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h
index 2623c97c9d..a9cfaeae22 100644
--- a/src/nvim/api/private/helpers.h
+++ b/src/nvim/api/private/helpers.h
@@ -34,6 +34,7 @@
.type = kObjectTypeString, \
.data.string = s })
+#define CSTR_AS_OBJ(s) STRING_OBJ(cstr_as_string(s))
#define CSTR_TO_OBJ(s) STRING_OBJ(cstr_to_string(s))
#define BUFFER_OBJ(s) ((Object) { \
@@ -103,6 +104,9 @@
.data = xmemdupz(s, sizeof(s) - 1), \
.size = sizeof(s) - 1 })
+#define STATIC_CSTR_AS_OBJ(s) STRING_OBJ(STATIC_CSTR_AS_STRING(s))
+#define STATIC_CSTR_TO_OBJ(s) STRING_OBJ(STATIC_CSTR_TO_STRING(s))
+
// Helpers used by the generated msgpack-rpc api wrappers
#define api_init_boolean
#define api_init_integer
@@ -122,13 +126,13 @@
#define api_free_window(value)
#define api_free_tabpage(value)
-EXTERN PMap(handle_T) buffer_handles INIT(= MAP_INIT);
-EXTERN PMap(handle_T) window_handles INIT(= MAP_INIT);
-EXTERN PMap(handle_T) tabpage_handles INIT(= MAP_INIT);
+EXTERN PMap(int) buffer_handles INIT(= MAP_INIT);
+EXTERN PMap(int) window_handles INIT(= MAP_INIT);
+EXTERN PMap(int) tabpage_handles INIT(= MAP_INIT);
-#define handle_get_buffer(h) pmap_get(handle_T)(&buffer_handles, (h))
-#define handle_get_window(h) pmap_get(handle_T)(&window_handles, (h))
-#define handle_get_tabpage(h) pmap_get(handle_T)(&tabpage_handles, (h))
+#define handle_get_buffer(h) pmap_get(int)(&buffer_handles, (h))
+#define handle_get_window(h) pmap_get(int)(&window_handles, (h))
+#define handle_get_tabpage(h) pmap_get(int)(&tabpage_handles, (h))
/// Structure used for saving state for :try
///
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index bd3482c85f..e98c589189 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -111,7 +111,7 @@ void remote_ui_disconnect(uint64_t channel_id)
}
UIData *data = ui->data;
kv_destroy(data->call_buf);
- pmap_del(uint64_t)(&connected_uis, channel_id);
+ pmap_del(uint64_t)(&connected_uis, channel_id, NULL);
ui_detach_impl(ui, channel_id);
// Destroy `ui`.
@@ -795,7 +795,7 @@ void remote_ui_put(UI *ui, const char *cell)
UIData *data = ui->data;
data->client_col++;
Array args = data->call_buf;
- ADD_C(args, STRING_OBJ(cstr_as_string((char *)cell)));
+ ADD_C(args, CSTR_AS_OBJ((char *)cell));
push_call(ui, "put", args);
}
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index d47f47e638..36163859eb 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -531,7 +531,7 @@ static void find_runtime_cb(char *fname, void *cookie)
{
Array *rv = (Array *)cookie;
if (fname != NULL) {
- ADD(*rv, STRING_OBJ(cstr_to_string(fname)));
+ ADD(*rv, CSTR_TO_OBJ(fname));
}
}
@@ -1383,7 +1383,7 @@ Dictionary nvim_get_mode(void)
get_mode(modestr);
bool blocked = input_blocking();
- PUT(rv, "mode", STRING_OBJ(cstr_to_string(modestr)));
+ PUT(rv, "mode", CSTR_TO_OBJ(modestr));
PUT(rv, "blocking", BOOLEAN_OBJ(blocked));
return rv;
@@ -1926,7 +1926,7 @@ Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Arena *arena, E
}
ret = arena_array(arena, 3);
size_t off = g->line_offset[(size_t)row] + (size_t)col;
- ADD_C(ret, STRING_OBJ(cstr_as_string((char *)g->chars[off])));
+ ADD_C(ret, CSTR_AS_OBJ((char *)g->chars[off]));
int attr = g->attrs[off];
ADD_C(ret, DICTIONARY_OBJ(hl_get_attr_by_id(attr, true, arena, err)));
// will not work first time
@@ -2035,7 +2035,7 @@ Array nvim_get_mark(String name, Dictionary opts, Error *err)
ADD(rv, INTEGER_OBJ(row));
ADD(rv, INTEGER_OBJ(col));
ADD(rv, INTEGER_OBJ(bufnr));
- ADD(rv, STRING_OBJ(cstr_to_string(filename)));
+ ADD(rv, CSTR_TO_OBJ(filename));
if (allocated) {
xfree(filename);
diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c
index 208aa165c9..1a67be8860 100644
--- a/src/nvim/api/vimscript.c
+++ b/src/nvim/api/vimscript.c
@@ -502,7 +502,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E
};
err_dict.items[0] = (KeyValuePair) {
.key = STATIC_CSTR_TO_STRING("message"),
- .value = STRING_OBJ(cstr_to_string(east.err.msg)),
+ .value = CSTR_TO_OBJ(east.err.msg),
};
if (east.err.arg == NULL) {
err_dict.items[1] = (KeyValuePair) {
@@ -539,7 +539,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E
chunk_arr.items[0] = INTEGER_OBJ((Integer)chunk.start.line);
chunk_arr.items[1] = INTEGER_OBJ((Integer)chunk.start.col);
chunk_arr.items[2] = INTEGER_OBJ((Integer)chunk.end_col);
- chunk_arr.items[3] = STRING_OBJ(cstr_to_string(chunk.group));
+ chunk_arr.items[3] = CSTR_TO_OBJ(chunk.group);
hl.items[i] = ARRAY_OBJ(chunk_arr);
}
ret.items[ret.size++] = (KeyValuePair) {
@@ -616,7 +616,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E
kv_drop(ast_conv_stack, 1);
ret_node->items[ret_node->size++] = (KeyValuePair) {
.key = STATIC_CSTR_TO_STRING("type"),
- .value = STRING_OBJ(cstr_to_string(east_node_type_tab[node->type])),
+ .value = CSTR_TO_OBJ(east_node_type_tab[node->type]),
};
Array start_array = {
.items = xmalloc(2 * sizeof(start_array.items[0])),
@@ -701,11 +701,11 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E
case kExprNodeComparison:
ret_node->items[ret_node->size++] = (KeyValuePair) {
.key = STATIC_CSTR_TO_STRING("cmp_type"),
- .value = STRING_OBJ(cstr_to_string(eltkn_cmp_type_tab[node->data.cmp.type])),
+ .value = CSTR_TO_OBJ(eltkn_cmp_type_tab[node->data.cmp.type]),
};
ret_node->items[ret_node->size++] = (KeyValuePair) {
.key = STATIC_CSTR_TO_STRING("ccs_strategy"),
- .value = STRING_OBJ(cstr_to_string(ccs_tab[node->data.cmp.ccs])),
+ .value = CSTR_TO_OBJ(ccs_tab[node->data.cmp.ccs]),
};
ret_node->items[ret_node->size++] = (KeyValuePair) {
.key = STATIC_CSTR_TO_STRING("invert"),
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index c267fee39a..8e4fbb6779 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -267,7 +267,7 @@ Dictionary nvim_win_get_config(Window window, Error *err)
PUT(rv, "bufpos", ARRAY_OBJ(pos));
}
}
- PUT(rv, "anchor", STRING_OBJ(cstr_to_string(float_anchor_str[config->anchor])));
+ PUT(rv, "anchor", CSTR_TO_OBJ(float_anchor_str[config->anchor]));
PUT(rv, "row", FLOAT_OBJ(config->row));
PUT(rv, "col", FLOAT_OBJ(config->col));
PUT(rv, "zindex", INTEGER_OBJ(config->zindex));
@@ -283,7 +283,7 @@ Dictionary nvim_win_get_config(Window window, Error *err)
char *hi_name = syn_id2name(hi_id);
if (hi_name[0]) {
ADD(tuple, STRING_OBJ(s));
- ADD(tuple, STRING_OBJ(cstr_to_string(hi_name)));
+ ADD(tuple, CSTR_TO_OBJ(hi_name));
ADD(border, ARRAY_OBJ(tuple));
} else {
ADD(border, STRING_OBJ(s));
@@ -297,7 +297,7 @@ Dictionary nvim_win_get_config(Window window, Error *err)
Array tuple = ARRAY_DICT_INIT;
ADD(tuple, CSTR_TO_OBJ(title_datas.items[i].text));
if (title_datas.items[i].hl_id > 0) {
- ADD(tuple, STRING_OBJ(cstr_to_string(syn_id2name(title_datas.items[i].hl_id))));
+ ADD(tuple, CSTR_TO_OBJ(syn_id2name(title_datas.items[i].hl_id)));
}
ADD(titles, ARRAY_OBJ(tuple));
}
@@ -317,7 +317,7 @@ Dictionary nvim_win_get_config(Window window, Error *err)
const char *rel = (wp->w_floating && !config->external
? float_relative_str[config->relative] : "");
- PUT(rv, "relative", STRING_OBJ(cstr_to_string(rel)));
+ PUT(rv, "relative", CSTR_TO_OBJ(rel));
return rv;
}
diff --git a/src/nvim/arglist.h b/src/nvim/arglist.h
index b2e0f411d4..cd34ca10c4 100644
--- a/src/nvim/arglist.h
+++ b/src/nvim/arglist.h
@@ -1,7 +1,7 @@
#ifndef NVIM_ARGLIST_H
#define NVIM_ARGLIST_H
-#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 2d5d8e262b..17a3fd33f1 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -108,14 +108,13 @@ static Map(int, String) map_augroup_id_to_name = MAP_INIT;
static void augroup_map_del(int id, const char *name)
{
if (name != NULL) {
- String key = map_key(String, int)(&map_augroup_name_to_id, cstr_as_string((char *)name));
- map_del(String, int)(&map_augroup_name_to_id, key);
+ String key;
+ map_del(String, int)(&map_augroup_name_to_id, cstr_as_string((char *)name), &key);
api_free_string(key);
}
if (id > 0) {
- String mapped = map_get(int, String)(&map_augroup_id_to_name, id);
+ String mapped = map_del(int, String)(&map_augroup_id_to_name, id, NULL);
api_free_string(mapped);
- map_del(int, String)(&map_augroup_id_to_name, id);
}
}
@@ -543,7 +542,7 @@ void do_augroup(char *arg, int del_group)
String name;
int value;
- map_foreach(&map_augroup_name_to_id, name, value, {
+ map_foreach(int, &map_augroup_name_to_id, name, value, {
if (value > 0) {
msg_puts(name.data);
} else {
@@ -572,18 +571,15 @@ void free_all_autocmds(void)
// Delete the augroup_map, including free the data
String name;
- int id;
- map_foreach(&map_augroup_name_to_id, name, id, {
- (void)id;
+ map_foreach_key(&map_augroup_name_to_id, name, {
api_free_string(name);
})
- map_destroy(String, int)(&map_augroup_name_to_id);
+ map_destroy(String, &map_augroup_name_to_id);
- map_foreach(&map_augroup_id_to_name, id, name, {
- (void)id;
+ map_foreach_value(String, &map_augroup_id_to_name, name, {
api_free_string(name);
})
- map_destroy(int, String)(&map_augroup_id_to_name);
+ map_destroy(int, &map_augroup_id_to_name);
// aucmd_win[] is freed in win_free_all()
}
@@ -1311,7 +1307,7 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
block_autocmds(); // We don't want BufEnter/WinEnter autocommands.
if (need_append) {
win_append(lastwin, auc_win);
- pmap_put(handle_T)(&window_handles, auc_win->handle, auc_win);
+ pmap_put(int)(&window_handles, auc_win->handle, auc_win);
win_config_float(auc_win, auc_win->w_float_config);
}
// Prevent chdir() call in win_enter_ext(), through do_autochdir()
@@ -1367,7 +1363,7 @@ win_found:
}
// Remove the window.
win_remove(curwin, NULL);
- pmap_del(handle_T)(&window_handles, curwin->handle);
+ pmap_del(int)(&window_handles, curwin->handle, NULL);
if (curwin->w_grid_alloc.chars != NULL) {
ui_comp_remove_grid(&curwin->w_grid_alloc);
ui_call_win_hide(curwin->w_grid_alloc.handle);
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 8d730733d0..11b79fcede 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -833,7 +833,7 @@ void buf_freeall(buf_T *buf, int flags)
/// itself (not the file, that must have been done already).
static void free_buffer(buf_T *buf)
{
- pmap_del(handle_T)(&buffer_handles, buf->b_fnum);
+ pmap_del(int)(&buffer_handles, buf->b_fnum, NULL);
buf_free_count++;
// b:changedtick uses an item in buf_T.
free_buffer_stuff(buf, kBffClearWinInfo);
@@ -1084,11 +1084,11 @@ char *do_bufdel(int command, char *arg, int addr_count, int start_bnr, int end_b
if (deleted == 0) {
if (command == DOBUF_UNLOAD) {
- STRCPY(IObuff, _("E515: No buffers were unloaded"));
+ xstrlcpy(IObuff, _("E515: No buffers were unloaded"), IOSIZE);
} else if (command == DOBUF_DEL) {
- STRCPY(IObuff, _("E516: No buffers were deleted"));
+ xstrlcpy(IObuff, _("E516: No buffers were deleted"), IOSIZE);
} else {
- STRCPY(IObuff, _("E517: No buffers were wiped out"));
+ xstrlcpy(IObuff, _("E517: No buffers were wiped out"), IOSIZE);
}
errormsg = IObuff;
} else if (deleted >= p_report) {
@@ -1459,16 +1459,11 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
// make "buf" the current buffer
if (action == DOBUF_SPLIT) { // split window first
- // If 'switchbuf' contains "useopen": jump to first window containing
- // "buf" if one exists
- if ((swb_flags & SWB_USEOPEN) && buf_jump_open_win(buf)) {
- return OK;
- }
- // If 'switchbuf' contains "usetab": jump to first window in any tab
- // page containing "buf" if one exists
- if ((swb_flags & SWB_USETAB) && buf_jump_open_tab(buf)) {
+ // If 'switchbuf' is set jump to the window containing "buf".
+ if (swbuf_goto_win_with_buf(buf) != NULL) {
return OK;
}
+
if (win_split(0, 0) == FAIL) {
return FAIL;
}
@@ -1870,7 +1865,7 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags)
lastbuf = buf;
buf->b_fnum = top_file_num++;
- pmap_put(handle_T)(&buffer_handles, buf->b_fnum, buf);
+ pmap_put(int)(&buffer_handles, buf->b_fnum, buf);
if (top_file_num < 0) { // wrap around (may cause duplicates)
emsg(_("W14: Warning: List of file names overflow"));
if (emsg_silent == 0 && !in_assert_fails) {
@@ -2072,17 +2067,8 @@ int buflist_getfile(int n, linenr_T lnum, int options, int forceit)
}
if (options & GETF_SWITCH) {
- // If 'switchbuf' contains "useopen": jump to first window containing
- // "buf" if one exists
- if (swb_flags & SWB_USEOPEN) {
- wp = buf_jump_open_win(buf);
- }
-
- // If 'switchbuf' contains "usetab": jump to first window in any tab
- // page containing "buf" if one exists
- if (wp == NULL && (swb_flags & SWB_USETAB)) {
- wp = buf_jump_open_tab(buf);
- }
+ // If 'switchbuf' is set jump to the window containing "buf".
+ wp = swbuf_goto_win_with_buf(buf);
// If 'switchbuf' contains "split", "vsplit" or "newtab" and the
// current buffer isn't empty: open new tab or window
@@ -3528,23 +3514,20 @@ bool append_arg_number(win_T *wp, char *buf, int buflen, bool add_file)
return false;
}
- char *p = buf + strlen(buf); // go to the end of the buffer
-
- // Early out if the string is getting too long
- if (p - buf + 35 >= buflen) {
- return false;
+ const char *msg;
+ switch ((wp->w_arg_idx_invalid ? 1 : 0) + (add_file ? 2 : 0)) {
+ case 0:
+ msg = _(" (%d of %d)"); break;
+ case 1:
+ msg = _(" ((%d) of %d)"); break;
+ case 2:
+ msg = _(" (file %d of %d)"); break;
+ case 3:
+ msg = _(" (file (%d) of %d)"); break;
}
- *p++ = ' ';
- *p++ = '(';
- if (add_file) {
- STRCPY(p, "file ");
- p += 5;
- }
- vim_snprintf(p, (size_t)(buflen - (p - buf)),
- wp->w_arg_idx_invalid
- ? "(%d) of %d)"
- : "%d of %d)", wp->w_arg_idx + 1, ARGCOUNT);
+ char *p = buf + strlen(buf); // go to the end of the buffer
+ vim_snprintf(p, (size_t)(buflen - (p - buf)), msg, wp->w_arg_idx + 1, ARGCOUNT);
return true;
}
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index ce8ee21882..f3f98bbd17 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -17,7 +17,7 @@ typedef struct {
#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
-#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/garray.h"
#include "nvim/grid_defs.h"
#include "nvim/hashtab.h"
@@ -808,6 +808,7 @@ struct file_buffer {
MarkTree b_marktree[1];
Map(uint32_t, uint32_t) b_extmark_ns[1]; // extmark namespaces
+ size_t b_virt_text_inline; // number of inline virtual texts
size_t b_virt_line_blocks; // number of virt_line blocks
size_t b_signs; // number of sign extmarks
size_t b_signs_with_text; // number of sign extmarks with text
diff --git a/src/nvim/bufwrite.c b/src/nvim/bufwrite.c
index 84c1276b8b..cfa3ea5bf3 100644
--- a/src/nvim/bufwrite.c
+++ b/src/nvim/bufwrite.c
@@ -745,7 +745,7 @@ static int buf_write_make_backup(char *fname, bool append, FileInfo *file_info_o
// the ones from the original file.
// First find a file name that doesn't exist yet (use some
// arbitrary numbers).
- STRCPY(IObuff, fname);
+ xstrlcpy(IObuff, fname, IOSIZE);
for (int i = 4913;; i += 123) {
char *tail = path_tail(IObuff);
size_t size = (size_t)(tail - IObuff);
@@ -1749,24 +1749,24 @@ restore_backup:
add_quoted_fname(IObuff, IOSIZE, buf, fname);
bool insert_space = false;
if (write_info.bw_conv_error) {
- STRCAT(IObuff, _(" CONVERSION ERROR"));
+ xstrlcat(IObuff, _(" CONVERSION ERROR"), IOSIZE);
insert_space = true;
if (write_info.bw_conv_error_lnum != 0) {
vim_snprintf_add(IObuff, IOSIZE, _(" in line %" PRId64 ";"),
(int64_t)write_info.bw_conv_error_lnum);
}
} else if (notconverted) {
- STRCAT(IObuff, _("[NOT converted]"));
+ xstrlcat(IObuff, _("[NOT converted]"), IOSIZE);
insert_space = true;
} else if (converted) {
- STRCAT(IObuff, _("[converted]"));
+ xstrlcat(IObuff, _("[converted]"), IOSIZE);
insert_space = true;
}
if (device) {
- STRCAT(IObuff, _("[Device]"));
+ xstrlcat(IObuff, _("[Device]"), IOSIZE);
insert_space = true;
} else if (newfile) {
- STRCAT(IObuff, new_file_message());
+ xstrlcat(IObuff, new_file_message(), IOSIZE);
insert_space = true;
}
if (no_eol) {
@@ -1780,9 +1780,9 @@ restore_backup:
msg_add_lines(insert_space, (long)lnum, nchars); // add line/char count
if (!shortmess(SHM_WRITE)) {
if (append) {
- STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"));
+ xstrlcat(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"), IOSIZE);
} else {
- STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [w]") : _(" written"));
+ xstrlcat(IObuff, shortmess(SHM_WRI) ? _(" [w]") : _(" written"), IOSIZE);
}
}
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 1d6869990e..9e1767c2f3 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -43,6 +43,7 @@
#include "nvim/plines.h"
#include "nvim/pos.h"
#include "nvim/search.h"
+#include "nvim/spell.h"
#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/textformat.h"
@@ -247,11 +248,25 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T
wp->w_redr_type = UPD_VALID;
}
+ linenr_T last = lnume + xtra - 1; // last line after the change
+
+ // Reset "w_skipcol" if the topline length has become smaller to
+ // such a degree that nothing will be visible anymore, accounting
+ // for 'smoothscroll' <<< or 'listchars' "precedes" marker.
+ if (wp->w_skipcol > 0
+ && (last < wp->w_topline
+ || (wp->w_topline >= lnum
+ && wp->w_topline < lnume
+ && win_linetabsize(wp, wp->w_topline, ml_get(wp->w_topline), (colnr_T)MAXCOL)
+ <= (unsigned)(wp->w_skipcol + sms_marker_overlap(wp, win_col_off(wp)
+ - win_col_off2(wp)))))) {
+ wp->w_skipcol = 0;
+ }
+
// Check if a change in the buffer has invalidated the cached
// values for the cursor.
// Update the folds for this window. Can't postpone this, because
// a following operator might work on the whole fold: ">>dd".
- linenr_T last = lnume + xtra - 1; // last line after the change
foldUpdate(wp, lnum, last);
// The change may cause lines above or below the change to become
@@ -379,6 +394,15 @@ void changed_bytes(linenr_T lnum, colnr_T col)
{
changedOneline(curbuf, lnum);
changed_common(lnum, col, lnum + 1, 0);
+ // When text has been changed at the end of the line, possibly the start of
+ // the next line may have SpellCap that should be removed or it needs to be
+ // displayed. Schedule the next line for redrawing just in case.
+ // Don't do this when displaying '$' at the end of changed text.
+ if (spell_check_window(curwin)
+ && lnum < curbuf->b_ml.ml_line_count
+ && vim_strchr(p_cpo, CPO_DOLLAR) == NULL) {
+ redrawWinline(curwin, lnum + 1);
+ }
// notify any channels that are watching
buf_updates_send_changes(curbuf, lnum, 1, 1);
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
index 820ce534e1..569d3f5887 100644
--- a/src/nvim/channel.c
+++ b/src/nvim/channel.c
@@ -57,7 +57,7 @@ void channel_teardown(void)
{
Channel *channel;
- map_foreach_value(&channels, channel, {
+ pmap_foreach_value(&channels, channel, {
channel_close(channel->id, kChannelPartAll, NULL);
});
}
@@ -279,7 +279,7 @@ static void free_channel_event(void **argv)
callback_reader_free(&chan->on_stderr);
callback_free(&chan->on_exit);
- pmap_del(uint64_t)(&channels, chan->id);
+ pmap_del(uint64_t)(&channels, chan->id, NULL);
multiqueue_free(chan->events);
xfree(chan);
}
@@ -289,7 +289,7 @@ static void channel_destroy_early(Channel *chan)
if ((chan->id != --next_chan_id)) {
abort();
}
- pmap_del(uint64_t)(&channels, chan->id);
+ pmap_del(uint64_t)(&channels, chan->id, NULL);
chan->id = 0;
if ((--chan->refcount != 0)) {
@@ -884,14 +884,14 @@ Dictionary channel_info(uint64_t id)
stream_desc = "job";
if (chan->stream.proc.type == kProcessTypePty) {
const char *name = pty_process_tty_name(&chan->stream.pty);
- PUT(info, "pty", STRING_OBJ(cstr_to_string(name)));
+ PUT(info, "pty", CSTR_TO_OBJ(name));
}
char **p = chan->stream.proc.argv;
Array argv = ARRAY_DICT_INIT;
if (p != NULL) {
while (*p != NULL) {
- ADD(argv, STRING_OBJ(cstr_to_string(*p)));
+ ADD(argv, CSTR_TO_OBJ(*p));
p++;
}
}
@@ -918,7 +918,7 @@ Dictionary channel_info(uint64_t id)
default:
abort();
}
- PUT(info, "stream", STRING_OBJ(cstr_to_string(stream_desc)));
+ PUT(info, "stream", CSTR_TO_OBJ(stream_desc));
if (chan->is_rpc) {
mode_desc = "rpc";
@@ -929,7 +929,7 @@ Dictionary channel_info(uint64_t id)
} else {
mode_desc = "bytes";
}
- PUT(info, "mode", STRING_OBJ(cstr_to_string(mode_desc)));
+ PUT(info, "mode", CSTR_TO_OBJ(mode_desc));
return info;
}
@@ -938,7 +938,7 @@ Array channel_all_info(void)
{
Channel *channel;
Array ret = ARRAY_DICT_INIT;
- map_foreach_value(&channels, channel, {
+ pmap_foreach_value(&channels, channel, {
ADD(ret, DICTIONARY_OBJ(channel_info(channel->id)));
});
return ret;
diff --git a/src/nvim/channel.h b/src/nvim/channel.h
index ca6c75b411..deb693373c 100644
--- a/src/nvim/channel.h
+++ b/src/nvim/channel.h
@@ -5,7 +5,6 @@
#include <stdint.h>
#include <stdlib.h>
-#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/event/libuv_process.h"
#include "nvim/event/multiqueue.h"
@@ -16,7 +15,6 @@
#include "nvim/macros.h"
#include "nvim/main.h"
#include "nvim/map.h"
-#include "nvim/map_defs.h"
#include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/os/pty_process.h"
#include "nvim/terminal.h"
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 8cae831881..49890a460a 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -989,6 +989,7 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
}
chartabsize_T cts;
+ bool on_NUL = false;
init_chartabsize_arg(&cts, wp, pos->lnum, 0, line, line);
// This function is used very often, do some speed optimizations.
@@ -1052,8 +1053,9 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
// make sure we don't go past the end of the line
if (*cts.cts_ptr == NUL) {
- // NUL at end of line only takes one column
- incr = 1;
+ // NUL at end of line only takes one column, unless there is virtual text
+ incr = MAX(1, cts.cts_cur_text_width_left + cts.cts_cur_text_width_right);
+ on_NUL = true;
break;
}
@@ -1079,8 +1081,6 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
}
if (cursor != NULL) {
- // cursor is after inserted text
- vcol += cts.cts_cur_text_width;
if ((*ptr == TAB)
&& (State & MODE_NORMAL)
&& !wp->w_p_list
@@ -1089,6 +1089,13 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
// cursor at end
*cursor = vcol + incr - 1;
} else {
+ if (!on_NUL) {
+ // cursor is after inserted text, unless on the NUL
+ vcol += cts.cts_cur_text_width_left;
+ if ((State & MODE_INSERT) == 0) {
+ vcol += cts.cts_cur_text_width_right;
+ }
+ }
// cursor at start
*cursor = vcol + head;
}
diff --git a/src/nvim/charset.h b/src/nvim/charset.h
index f98ed94b87..258e95bec0 100644
--- a/src/nvim/charset.h
+++ b/src/nvim/charset.h
@@ -4,7 +4,7 @@
#include <stdbool.h>
#include "nvim/buffer_defs.h"
-#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/option_defs.h"
#include "nvim/pos.h"
#include "nvim/strings.h"
diff --git a/src/nvim/cmdexpand.h b/src/nvim/cmdexpand.h
index 810e289f7c..32c23c5d66 100644
--- a/src/nvim/cmdexpand.h
+++ b/src/nvim/cmdexpand.h
@@ -1,7 +1,7 @@
#ifndef NVIM_CMDEXPAND_H
#define NVIM_CMDEXPAND_H
-#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_getln.h"
#include "nvim/garray.h"
#include "nvim/types.h"
diff --git a/src/nvim/cmdhist.c b/src/nvim/cmdhist.c
index 81b93e5304..fc84cecc1a 100644
--- a/src/nvim/cmdhist.c
+++ b/src/nvim/cmdhist.c
@@ -641,9 +641,10 @@ void ex_history(exarg_T *eap)
}
for (; !got_int && histype1 <= histype2; histype1++) {
- STRCPY(IObuff, "\n # ");
+ xstrlcpy(IObuff, "\n # ", IOSIZE);
assert(history_names[histype1] != NULL);
- STRCAT(STRCAT(IObuff, history_names[histype1]), " history");
+ xstrlcat(IObuff, history_names[histype1], IOSIZE);
+ xstrlcat(IObuff, " history", IOSIZE);
msg_puts_title(IObuff);
int idx = hisidx[histype1];
histentry_T *hist = history[histype1];
@@ -669,7 +670,7 @@ void ex_history(exarg_T *eap)
trunc_string(hist[i].hisstr, IObuff + strlen(IObuff),
Columns - 10, IOSIZE - (int)strlen(IObuff));
} else {
- STRCAT(IObuff, hist[i].hisstr);
+ xstrlcat(IObuff, hist[i].hisstr, IOSIZE);
}
msg_outtrans(IObuff);
}
diff --git a/src/nvim/cmdhist.h b/src/nvim/cmdhist.h
index f86a2f855c..a0f2ab6934 100644
--- a/src/nvim/cmdhist.h
+++ b/src/nvim/cmdhist.h
@@ -1,7 +1,6 @@
#ifndef NVIM_CMDHIST_H
#define NVIM_CMDHIST_H
-#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/os/time.h"
diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c
index 428f9f28e4..4e5886406a 100644
--- a/src/nvim/cursor_shape.c
+++ b/src/nvim/cursor_shape.c
@@ -62,8 +62,8 @@ Array mode_style_array(Arena *arena)
for (int i = 0; i < SHAPE_IDX_COUNT; i++) {
cursorentry_T *cur = &shape_table[i];
Dictionary dic = arena_dict(arena, 3 + ((cur->used_for & SHAPE_CURSOR) ? 9 : 0));
- PUT_C(dic, "name", STRING_OBJ(cstr_as_string(cur->full_name)));
- PUT_C(dic, "short_name", STRING_OBJ(cstr_as_string(cur->name)));
+ PUT_C(dic, "name", CSTR_AS_OBJ(cur->full_name));
+ PUT_C(dic, "short_name", CSTR_AS_OBJ(cur->name));
if (cur->used_for & SHAPE_MOUSE) {
PUT_C(dic, "mouse_shape", INTEGER_OBJ(cur->mshape));
}
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 87e4441f32..ce1af290c1 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -83,6 +83,9 @@ void decor_redraw(buf_T *buf, int row1, int row2, Decoration *decor)
if (decor && decor_virt_pos(*decor)) {
redraw_buf_line_later(buf, row1 + 1, false);
+ if (decor->virt_text_pos == kVTInline) {
+ changed_line_display_buf(buf);
+ }
}
if (decor && kv_size(decor->virt_lines)) {
@@ -95,6 +98,10 @@ void decor_remove(buf_T *buf, int row, int row2, Decoration *decor)
{
decor_redraw(buf, row, row2, decor);
if (decor) {
+ if (kv_size(decor->virt_text) && decor->virt_text_pos == kVTInline) {
+ assert(buf->b_virt_text_inline > 0);
+ buf->b_virt_text_inline--;
+ }
if (kv_size(decor->virt_lines)) {
assert(buf->b_virt_line_blocks > 0);
buf->b_virt_line_blocks--;
diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h
index 92001d496d..95c9655742 100644
--- a/src/nvim/decoration.h
+++ b/src/nvim/decoration.h
@@ -23,9 +23,11 @@ typedef enum {
kVTOverlay,
kVTWinCol,
kVTRightAlign,
+ kVTInline,
} VirtTextPos;
-EXTERN const char *const virt_text_pos_str[] INIT(= { "eol", "overlay", "win_col", "right_align" });
+EXTERN const char *const virt_text_pos_str[] INIT(= { "eol", "overlay", "win_col", "right_align",
+ "inline" });
typedef enum {
kHlModeUnknown,
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index e6cdf3d60d..d2d39e8ca8 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -2,7 +2,7 @@
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// drawline.c: Functions for drawing window lines on the screen.
-// This is the middle level, drawscreen.c is the top and grid.c/screen.c the lower level.
+// This is the middle level, drawscreen.c is the top and grid.c the lower level.
#include <assert.h>
#include <limits.h>
@@ -98,6 +98,7 @@ typedef struct {
int char_attr; ///< attributes for next character
int n_extra; ///< number of extra bytes
+ int n_attr; ///< chars with special attr
char *p_extra; ///< string of extra chars, plus NUL, only used
///< when c_extra and c_final are NUL
char *p_extra_free; ///< p_extra buffer that needs to be freed
@@ -105,9 +106,12 @@ typedef struct {
int c_extra; ///< extra chars, all the same
int c_final; ///< final char, mandatory if set
+ bool extra_for_extmark;
+
// saved "extra" items for when draw_state becomes WL_LINE (again)
int saved_n_extra;
char *saved_p_extra;
+ bool saved_extra_for_extmark;
int saved_c_extra;
int saved_c_final;
int saved_char_attr;
@@ -120,6 +124,14 @@ typedef struct {
int filler_lines; ///< nr of filler lines to be drawn
int filler_todo; ///< nr of filler lines still to do + 1
SignTextAttrs sattrs[SIGN_SHOW_MAX]; ///< sign attributes for the sign column
+
+ VirtText virt_inline;
+ size_t virt_inline_i;
+
+ bool reset_extra_attr;
+
+ int skip_cells; // nr of cells to skip for virtual text
+ int skipped_cells; // nr of skipped virtual text cells
} winlinevars_T;
/// for line_putchar. Contains the state that needs to be remembered from
@@ -342,12 +354,20 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode,
schar_T dummy[2];
int cells = line_putchar(buf, &s, through ? dummy : &linebuf_char[col],
max_col - col, false, vcol);
- // if we failed to emit a char, we still need to advance
- cells = MAX(cells, 1);
-
+ // If we failed to emit a char, we still need to put a space and advance.
+ if (cells < 1) {
+ schar_from_ascii(linebuf_char[col], ' ');
+ cells = 1;
+ }
for (int c = 0; c < cells; c++) {
linebuf_attr[col++] = attr;
}
+ if (col < max_col && linebuf_char[col][0] == 0) {
+ // If the left half of a double-width char is overwritten,
+ // change the right half to a space so that grid redraws properly,
+ // but don't advance the current column.
+ schar_from_ascii(linebuf_char[col], ' ');
+ }
vcol += cells;
}
return col;
@@ -843,6 +863,73 @@ static void apply_cursorline_highlight(win_T *wp, winlinevars_T *wlv)
}
}
+static void handle_inline_virtual_text(win_T *wp, winlinevars_T *wlv, ptrdiff_t v, bool *do_save)
+{
+ while (true) {
+ // we could already be inside an existing inline text with multiple chunks
+ if (!(wlv->virt_inline_i < kv_size(wlv->virt_inline))) {
+ DecorState *state = &decor_state;
+ for (size_t i = 0; i < kv_size(state->active); i++) {
+ DecorRange *item = &kv_A(state->active, i);
+ if (item->start_row != state->row
+ || !kv_size(item->decor.virt_text)
+ || item->decor.virt_text_pos != kVTInline) {
+ continue;
+ }
+ if (item->win_col >= -1 && item->start_col == v) {
+ wlv->virt_inline = item->decor.virt_text;
+ wlv->virt_inline_i = 0;
+ item->win_col = -2;
+ break;
+ }
+ }
+ }
+
+ if (wlv->n_extra == 0 || !wlv->extra_for_extmark) {
+ wlv->reset_extra_attr = false;
+ }
+
+ if (wlv->n_extra <= 0 && wlv->virt_inline_i < kv_size(wlv->virt_inline)) {
+ VirtTextChunk vtc = kv_A(wlv->virt_inline, wlv->virt_inline_i);
+ wlv->p_extra = vtc.text;
+ wlv->n_extra = (int)strlen(wlv->p_extra);
+ wlv->extra_for_extmark = true;
+ wlv->c_extra = NUL;
+ wlv->c_final = NUL;
+ wlv->extra_attr = vtc.hl_id ? syn_id2attr(vtc.hl_id) : 0;
+ wlv->n_attr = mb_charlen(vtc.text);
+ wlv->virt_inline_i++;
+ *do_save = true;
+ // If the text didn't reach until the first window
+ // column we need to skip cells.
+ if (wlv->skip_cells > 0) {
+ int virt_text_len = wlv->n_attr;
+ if (virt_text_len > wlv->skip_cells) {
+ int len = mb_charlen2bytelen(wlv->p_extra, wlv->skip_cells);
+ wlv->n_extra -= len;
+ wlv->p_extra += len;
+ wlv->n_attr -= wlv->skip_cells;
+ // Skipped cells needed to be accounted for in vcol.
+ wlv->skipped_cells += wlv->skip_cells;
+ wlv->skip_cells = 0;
+ } else {
+ // the whole text is left of the window, drop
+ // it and advance to the next one
+ wlv->skip_cells -= virt_text_len;
+ // Skipped cells needed to be accounted for in vcol.
+ wlv->skipped_cells += virt_text_len;
+ wlv->n_attr = 0;
+ wlv->n_extra = 0;
+
+ // go to the start so the next virtual text chunk can be selected.
+ continue;
+ }
+ }
+ }
+ break;
+ }
+}
+
static bool check_mb_utf8(int *c, int *u8cc)
{
if (utf_char2len(*c) > 1) {
@@ -909,6 +996,7 @@ static void win_line_start(win_T *wp, winlinevars_T *wlv, bool save_extra)
wlv->draw_state = WL_START;
wlv->saved_n_extra = wlv->n_extra;
wlv->saved_p_extra = wlv->p_extra;
+ wlv->saved_extra_for_extmark = wlv->extra_for_extmark;
wlv->saved_c_extra = wlv->c_extra;
wlv->saved_c_final = wlv->c_final;
wlv->saved_char_attr = wlv->char_attr;
@@ -923,6 +1011,8 @@ static void win_line_continue(winlinevars_T *wlv)
if (wlv->saved_n_extra > 0) {
// Continue item from end of wrapped line.
wlv->n_extra = wlv->saved_n_extra;
+ wlv->saved_n_extra = 0;
+ wlv->extra_for_extmark = wlv->saved_extra_for_extmark;
wlv->c_extra = wlv->saved_c_extra;
wlv->c_final = wlv->saved_c_final;
wlv->p_extra = wlv->saved_p_extra;
@@ -938,7 +1028,7 @@ static void win_line_continue(winlinevars_T *wlv)
/// @param lnum line to display
/// @param startrow first row relative to window grid
/// @param endrow last grid row to be redrawn
-/// @param nochange not updating for changed text
+/// @param mod_top top line updated for changed text
/// @param number_only only update the number column
/// @param foldinfo fold info for this line
/// @param[in, out] providers decoration providers active this line
@@ -946,7 +1036,7 @@ static void win_line_continue(winlinevars_T *wlv)
/// or explicitly return `false`.
///
/// @return the number of last row the line occupies.
-int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, bool number_only,
+int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int mod_top, bool number_only,
foldinfo_T foldinfo, DecorProviders *providers, char **provider_err)
{
winlinevars_T wlv; // variables passed between functions
@@ -959,14 +1049,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
static char *at_end_str = ""; // used for p_extra when displaying curwin->w_p_lcs_chars.eol
// at end-of-line
- bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0;
+ const bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0;
- int n_attr = 0; // chars with special attr
int saved_attr2 = 0; // char_attr saved for n_attr
int n_attr3 = 0; // chars with overruling special attr
int saved_attr3 = 0; // char_attr saved for n_attr3
- int n_skip = 0; // nr of chars to skip for 'nowrap'
+ int n_skip = 0; // nr of chars to skip for 'nowrap' or
+ // concealing
int fromcol_prev = -2; // start of inverting after cursor
bool noinvcur = false; // don't invert the cursor
@@ -978,10 +1068,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
bool area_highlighting = false; // Visual or incsearch highlighting in this line
int vi_attr = 0; // attributes for Visual and incsearch highlighting
int area_attr = 0; // attributes desired by highlighting
+ int saved_area_attr = 0; // idem for area_attr
int search_attr = 0; // attributes desired by 'hlsearch'
+ int saved_search_attr = 0; // search_attr to be used when n_extra
+ // goes to zero
int vcol_save_attr = 0; // saved attr for 'cursorcolumn'
int syntax_attr = 0; // attributes desired by syntax
bool has_syntax = false; // this buffer has syntax highl.
+ int folded_attr = 0; // attributes for folded line
int save_did_emsg;
int eol_hl_off = 0; // 1 if highlighted char after EOL
bool draw_color_col = false; // highlight colorcolumn
@@ -1016,6 +1110,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
int prev_c1 = 0; // first composing char for prev_c
bool search_attr_from_match = false; // if search_attr is from :match
+ bool saved_search_attr_from_match = false; // if search_attr is from :match
bool has_decor = false; // this buffer has decoration
int win_col_offset = 0; // offset for window columns
@@ -1065,7 +1160,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.vcol_sbr = -1;
buf_T *buf = wp->w_buffer;
- bool end_fill = (lnum == buf->b_ml.ml_line_count + 1);
+ const bool end_fill = (lnum == buf->b_ml.ml_line_count + 1);
if (!number_only) {
// To speed up the loop below, set extra_check when there is linebreak,
@@ -1109,12 +1204,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
}
- if (wp->w_p_spell
- && !has_fold
- && !end_fill
- && *wp->w_s->b_p_spl != NUL
- && !GA_EMPTY(&wp->w_s->b_langp)
- && *(char **)(wp->w_s->b_langp.ga_data) != NULL) {
+ if (!has_fold && !end_fill && spell_check_window(wp)) {
// Prepare for spell checking.
has_spell = true;
extra_check = true;
@@ -1137,12 +1227,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// When there was a sentence end in the previous line may require a
// word starting with capital in this line. In line 1 always check
- // the first word.
- if (lnum != capcol_lnum) {
- cap_col = -1;
- }
- if (lnum == 1) {
+ // the first word. Also check for sentence end in the line above
+ // when updating the first row in a window, the top line with
+ // changed text in a window, or if the previous line is folded.
+ if (lnum == 1
+ || ((startrow == 0 || mod_top == lnum
+ || hasFoldingWin(wp, lnum - 1, NULL, NULL, true, NULL))
+ && check_need_cap(wp, lnum, 0))) {
cap_col = 0;
+ } else if (lnum != capcol_lnum) {
+ cap_col = -1;
}
capcol_lnum = 0;
}
@@ -1428,6 +1522,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
}
+ // If there the text doesn't reach to the desired column, need to skip
+ // "skip_cells" cells when virtual text follows.
+ if (!wp->w_p_wrap && v > wlv.vcol) {
+ wlv.skip_cells = (int)(v - wlv.vcol);
+ }
+
// Adjust for when the inverted text is before the screen,
// and when the start of the inverted text is before the screen.
if (wlv.tocol <= wlv.vcol) {
@@ -1594,6 +1694,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// Draw the 'statuscolumn' if option is set.
if (statuscol.draw) {
if (statuscol.textp == NULL) {
+ v = (ptr - line);
get_statuscol_str(wp, lnum, wlv.row - startrow - wlv.filler_lines, &statuscol);
if (!end_fill) {
// Get the line again as evaluating 'statuscolumn' may free it.
@@ -1628,7 +1729,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.draw_state = WL_LINE;
if (has_decor && wlv.row == startrow + wlv.filler_lines) {
// hide virt_text on text hidden by 'nowrap'
- decor_redraw_col(wp, wlv.vcol, wlv.off, true, &decor_state);
+ decor_redraw_col(wp, (colnr_T)(ptr - line), wlv.off, true, &decor_state);
}
win_line_continue(&wlv); // use wlv.saved_ values
}
@@ -1664,7 +1765,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& wlv.col == win_col_offset
&& wlv.n_extra == 0
&& wlv.row == startrow + wlv.filler_lines) {
- wlv.char_attr = win_hl_attr(wp, HLF_FL);
+ wlv.char_attr = folded_attr = win_hl_attr(wp, HLF_FL);
linenr_T lnume = lnum + foldinfo.fi_lines - 1;
memset(buf_fold, ' ', FOLD_TEXT_LEN);
@@ -1705,7 +1806,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.n_extra = 0;
}
- if (wlv.draw_state == WL_LINE && (area_highlighting || has_spell)) {
+ int extmark_attr = 0;
+ if (wlv.draw_state == WL_LINE
+ && (area_highlighting || has_spell || extra_check)) {
// handle Visual or match highlighting in this line
if (wlv.vcol == wlv.fromcol
|| (wlv.vcol + 1 == wlv.fromcol && wlv.n_extra == 0
@@ -1723,39 +1826,65 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
area_active = false;
}
- if (!wlv.n_extra) {
- // Check for start/end of 'hlsearch' and other matches.
- // After end, check for start/end of next match.
- // When another match, have to check for start again.
- v = (ptr - line);
- search_attr = update_search_hl(wp, lnum, (colnr_T)v, &line, &screen_search_hl,
- &has_match_conc, &match_conc, lcs_eol_one,
- &on_last_col, &search_attr_from_match);
- ptr = line + v; // "line" may have been changed
-
- // Do not allow a conceal over EOL otherwise EOL will be missed
- // and bad things happen.
- if (*ptr == NUL) {
- has_match_conc = 0;
+ if (!has_fold) {
+ if (has_decor && v >= 0) {
+ bool selected = (area_active || (area_highlighting && noinvcur
+ && wlv.vcol == wp->w_virtcol));
+ extmark_attr = decor_redraw_col(wp, (colnr_T)v, wlv.off,
+ selected, &decor_state);
+
+ bool do_save = false;
+ handle_inline_virtual_text(wp, &wlv, v, &do_save);
+ if (do_save) {
+ // restore search_attr and area_attr when n_extra is down to zero
+ // TODO(bfredl): this is ugly as fuck. look if we can do this some other way.
+ saved_search_attr = search_attr;
+ saved_area_attr = area_attr;
+ saved_search_attr_from_match = search_attr_from_match;
+ search_attr_from_match = false;
+ search_attr = 0;
+ area_attr = 0;
+ extmark_attr = 0;
+ n_skip = 0;
+ }
}
- }
- if (wlv.diff_hlf != (hlf_T)0) {
- if (wlv.diff_hlf == HLF_CHD && ptr - line >= change_start
- && wlv.n_extra == 0) {
- wlv.diff_hlf = HLF_TXD; // changed text
- }
- if (wlv.diff_hlf == HLF_TXD && ptr - line > change_end
- && wlv.n_extra == 0) {
- wlv.diff_hlf = HLF_CHD; // changed line
+ if (wlv.n_extra == 0) {
+ // Check for start/end of 'hlsearch' and other matches.
+ // After end, check for start/end of next match.
+ // When another match, have to check for start again.
+ v = (ptr - line);
+ search_attr = update_search_hl(wp, lnum, (colnr_T)v, &line, &screen_search_hl,
+ &has_match_conc, &match_conc, lcs_eol_one,
+ &on_last_col, &search_attr_from_match);
+ ptr = line + v; // "line" may have been changed
+
+ // Do not allow a conceal over EOL otherwise EOL will be missed
+ // and bad things happen.
+ if (*ptr == NUL) {
+ has_match_conc = 0;
+ }
}
- wlv.line_attr = win_hl_attr(wp, (int)wlv.diff_hlf);
- // Overlay CursorLine onto diff-mode highlight.
- if (wlv.cul_attr) {
- wlv.line_attr = 0 != wlv.line_attr_lowprio // Low-priority CursorLine
- ? hl_combine_attr(hl_combine_attr(wlv.cul_attr, wlv.line_attr),
- hl_get_underline())
- : hl_combine_attr(wlv.line_attr, wlv.cul_attr);
+
+ if (wlv.diff_hlf != (hlf_T)0) {
+ // When there is extra text (eg: virtual text) it gets the
+ // diff highlighting for the line, but not for changed text.
+ if (wlv.diff_hlf == HLF_CHD && ptr - line >= change_start
+ && wlv.n_extra == 0) {
+ wlv.diff_hlf = HLF_TXD; // changed text
+ }
+ if (wlv.diff_hlf == HLF_TXD && ((ptr - line > change_end && wlv.n_extra == 0)
+ || (wlv.n_extra > 0 && wlv.extra_for_extmark))) {
+ wlv.diff_hlf = HLF_CHD; // changed line
+ }
+ wlv.line_attr = win_hl_attr(wp, (int)wlv.diff_hlf);
+ // Overlay CursorLine onto diff-mode highlight.
+ if (wlv.cul_attr) {
+ wlv.line_attr = 0 != wlv.line_attr_lowprio // Low-priority CursorLine
+ ? hl_combine_attr(hl_combine_attr(wlv.cul_attr, wlv.line_attr),
+ hl_get_underline())
+ : hl_combine_attr(wlv.line_attr, wlv.cul_attr);
+ }
}
}
@@ -1786,6 +1915,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.char_attr = 0;
}
}
+
+ if (folded_attr != 0) {
+ wlv.char_attr = hl_combine_attr(folded_attr, wlv.char_attr);
+ }
}
// Get the next character to put on the screen.
@@ -1847,6 +1980,26 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.p_extra++;
}
wlv.n_extra--;
+
+ // Only restore search_attr and area_attr after "n_extra" in
+ // the next screen line is also done.
+ if (wlv.n_extra <= 0) {
+ if (wlv.saved_n_extra <= 0) {
+ if (search_attr == 0) {
+ search_attr = saved_search_attr;
+ }
+ if (area_attr == 0 && *ptr != NUL) {
+ area_attr = saved_area_attr;
+ }
+
+ if (wlv.extra_for_extmark) {
+ // wlv.extra_attr should be used at this position but not
+ // any further.
+ wlv.reset_extra_attr = true;
+ }
+ }
+ wlv.extra_for_extmark = false;
+ }
} else if (foldinfo.fi_lines > 0) {
// skip writing the buffer line itself
c = NUL;
@@ -1898,7 +2051,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.c_extra = NUL;
wlv.c_final = NUL;
if (area_attr == 0 && search_attr == 0) {
- n_attr = wlv.n_extra + 1;
+ wlv.n_attr = wlv.n_extra + 1;
wlv.extra_attr = win_hl_attr(wp, HLF_8);
saved_attr2 = wlv.char_attr; // save current attr
}
@@ -1953,7 +2106,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.c_final = NUL;
c = ' ';
if (area_attr == 0 && search_attr == 0) {
- n_attr = wlv.n_extra + 1;
+ wlv.n_attr = wlv.n_extra + 1;
wlv.extra_attr = win_hl_attr(wp, HLF_AT);
saved_attr2 = wlv.char_attr; // save current attr
}
@@ -2018,10 +2171,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
if (has_decor && v > 0) {
- bool selected = (area_active || (area_highlighting && noinvcur
- && wlv.vcol == wp->w_virtcol));
- int extmark_attr = decor_redraw_col(wp, (colnr_T)v - 1, wlv.off,
- selected, &decor_state);
if (extmark_attr != 0) {
if (!attr_pri) {
wlv.char_attr = hl_combine_attr(wlv.char_attr, extmark_attr);
@@ -2045,15 +2194,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
v = (ptr - line);
if (has_spell && v >= word_end && v > cur_checked_col) {
spell_attr = 0;
- if (!attr_pri) {
- wlv.char_attr = hl_combine_attr(wlv.char_attr, syntax_attr);
- }
- if (c != 0 && ((!has_syntax && !no_plain_buffer) || can_spell)) {
- char *prev_ptr;
+ char *prev_ptr = ptr - mb_l;
+ // do not calculate cap_col at the end of the line or when
+ // only white space is following
+ if (c != 0 && (*skipwhite(prev_ptr) != NUL)
+ && ((!has_syntax && !no_plain_buffer) || can_spell)) {
char *p;
- int len;
hlf_T spell_hlf = HLF_COUNT;
- prev_ptr = ptr - mb_l;
v -= mb_l - 1;
// Use nextline[] if possible, it has the start of the
@@ -2064,9 +2211,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
p = prev_ptr;
}
cap_col -= (int)(prev_ptr - line);
- size_t tmplen = spell_check(wp, p, &spell_hlf, &cap_col, nochange);
+ size_t tmplen = spell_check(wp, p, &spell_hlf, &cap_col, mod_top == 0);
assert(tmplen <= INT_MAX);
- len = (int)tmplen;
+ int len = (int)tmplen;
word_end = (int)v + len;
// In Insert mode only highlight a word that
@@ -2129,7 +2276,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
chartabsize_T cts;
init_chartabsize_arg(&cts, wp, lnum, wlv.vcol, line, p);
+ // do not want virtual text to be counted here
+ cts.cts_has_virt_text = false;
wlv.n_extra = win_lbr_chartabsize(&cts, NULL) - 1;
+ clear_chartabsize_arg(&cts);
// We have just drawn the showbreak value, no need to add
// space for it again.
@@ -2161,7 +2311,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
c = ' ';
}
}
- clear_chartabsize_arg(&cts);
}
in_multispace = c == ' ' && ((ptr > line + 1 && ptr[-2] == ' ') || *ptr == ' ');
@@ -2192,7 +2341,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
} else {
c = (c == ' ') ? wp->w_p_lcs_chars.space : wp->w_p_lcs_chars.nbsp;
}
- n_attr = 1;
+ wlv.n_attr = 1;
wlv.extra_attr = win_hl_attr(wp, HLF_0);
saved_attr2 = wlv.char_attr; // save current attr
mb_c = c;
@@ -2215,7 +2364,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
c = wp->w_p_lcs_chars.space;
}
- n_attr = 1;
+ wlv.n_attr = 1;
wlv.extra_attr = win_hl_attr(wp, HLF_0);
saved_attr2 = wlv.char_attr; // save current attr
mb_c = c;
@@ -2331,7 +2480,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.c_extra = wp->w_p_lcs_chars.tab2;
}
wlv.c_final = wp->w_p_lcs_chars.tab3;
- n_attr = tab_len + 1;
+ wlv.n_attr = tab_len + 1;
wlv.extra_attr = win_hl_attr(wp, HLF_0);
saved_attr2 = wlv.char_attr; // save current attr
mb_c = c;
@@ -2358,15 +2507,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& wlv.line_attr == 0
&& wlv.line_attr_lowprio == 0) {
// In virtualedit, visual selections may extend beyond end of line
- if (area_highlighting && virtual_active()
- && wlv.tocol != MAXCOL && wlv.vcol < wlv.tocol) {
- wlv.n_extra = 0;
- } else {
+ if (!(area_highlighting && virtual_active()
+ && wlv.tocol != MAXCOL && wlv.vcol < wlv.tocol)) {
wlv.p_extra = at_end_str;
- wlv.n_extra = 1;
- wlv.c_extra = NUL;
- wlv.c_final = NUL;
}
+ wlv.n_extra = 0;
}
if (wp->w_p_list && wp->w_p_lcs_chars.eol > 0) {
c = wp->w_p_lcs_chars.eol;
@@ -2376,7 +2521,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
lcs_eol_one = -1;
ptr--; // put it back at the NUL
wlv.extra_attr = win_hl_attr(wp, HLF_AT);
- n_attr = 1;
+ wlv.n_attr = 1;
mb_c = c;
mb_utf8 = check_mb_utf8(&c, u8cc);
} else if (c != NUL) {
@@ -2405,7 +2550,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.n_extra = byte2cells(c) - 1;
c = (uint8_t)(*wlv.p_extra++);
}
- n_attr = wlv.n_extra + 1;
+ wlv.n_attr = wlv.n_extra + 1;
wlv.extra_attr = win_hl_attr(wp, HLF_8);
saved_attr2 = wlv.char_attr; // save current attr
mb_utf8 = false; // don't draw as UTF-8
@@ -2465,7 +2610,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
}
wlv.n_extra = 0;
- n_attr = 0;
+ wlv.n_attr = 0;
} else if (n_skip == 0) {
is_concealing = true;
n_skip = 1;
@@ -2500,8 +2645,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
// Don't override visual selection highlighting.
- if (n_attr > 0 && wlv.draw_state == WL_LINE && !search_attr_from_match) {
+ if (wlv.n_attr > 0 && wlv.draw_state == WL_LINE && !search_attr_from_match) {
wlv.char_attr = hl_combine_attr(wlv.char_attr, wlv.extra_attr);
+ if (wlv.reset_extra_attr) {
+ wlv.reset_extra_attr = false;
+ wlv.extra_attr = 0;
+ // search_attr_from_match can be restored now that the extra_attr has been applied
+ search_attr_from_match = saved_search_attr_from_match;
+ }
}
// Handle the case where we are in column 0 but not on the first
@@ -2521,7 +2672,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.c_extra = MB_FILLER_CHAR;
wlv.c_final = NUL;
wlv.n_extra = 1;
- n_attr = 2;
+ wlv.n_attr = 2;
wlv.extra_attr = win_hl_attr(wp, HLF_AT);
}
mb_c = c;
@@ -2737,7 +2888,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& !has_fold
&& (*ptr != NUL
|| lcs_eol_one > 0
- || (wlv.n_extra && (wlv.c_extra != NUL || *wlv.p_extra != NUL)))) {
+ || (wlv.n_extra > 0 && (wlv.c_extra != NUL || *wlv.p_extra != NUL)))) {
c = wp->w_p_lcs_chars.ext;
wlv.char_attr = win_hl_attr(wp, HLF_AT);
mb_c = c;
@@ -2808,6 +2959,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.col++;
// UTF-8: Put a 0 in the second screen char.
linebuf_char[wlv.off][0] = 0;
+ linebuf_attr[wlv.off] = linebuf_attr[wlv.off - 1];
if (wlv.draw_state > WL_STC && wlv.filler_todo <= 0) {
wlv.vcol++;
}
@@ -2857,7 +3009,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.boguscols += wlv.n_extra;
}
wlv.n_extra = 0;
- n_attr = 0;
+ wlv.n_attr = 0;
}
if (utf_char2cells(mb_c) > 1) {
@@ -2882,13 +3034,19 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (wlv.n_extra > 0) {
wlv.vcol += wlv.n_extra;
wlv.n_extra = 0;
- n_attr = 0;
+ wlv.n_attr = 0;
}
}
} else {
n_skip--;
}
+ // The skipped cells need to be accounted for in vcol.
+ if (wlv.draw_state > WL_STC && wlv.skipped_cells > 0) {
+ wlv.vcol += wlv.skipped_cells;
+ wlv.skipped_cells = 0;
+ }
+
// Only advance the "wlv.vcol" when after the 'number' or
// 'relativenumber' column.
if (wlv.draw_state > WL_STC
@@ -2906,7 +3064,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
// restore attributes after last 'listchars' or 'number' char
- if (n_attr > 0 && wlv.draw_state == WL_LINE && --n_attr == 0) {
+ if (wlv.n_attr > 0 && wlv.draw_state == WL_LINE && --wlv.n_attr == 0) {
wlv.char_attr = saved_attr2;
}
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c
index 7f7c721379..4f79ba87af 100644
--- a/src/nvim/drawscreen.c
+++ b/src/nvim/drawscreen.c
@@ -2222,9 +2222,8 @@ static void win_update(win_T *wp, DecorProviders *providers)
}
// Display one line
- row = win_line(wp, lnum, srow,
- foldinfo.fi_lines ? srow : wp->w_grid.rows,
- mod_top == 0, false, foldinfo, &line_providers, &provider_err);
+ row = win_line(wp, lnum, srow, foldinfo.fi_lines ? srow : wp->w_grid.rows,
+ mod_top, false, foldinfo, &line_providers, &provider_err);
if (foldinfo.fi_lines == 0) {
wp->w_lines[idx].wl_folded = false;
@@ -2261,7 +2260,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
// text doesn't need to be drawn, but the number column does.
foldinfo_T info = wp->w_p_cul && lnum == wp->w_cursor.lnum ?
cursorline_fi : fold_info(wp, lnum);
- (void)win_line(wp, lnum, srow, wp->w_grid.rows, true, true,
+ (void)win_line(wp, lnum, srow, wp->w_grid.rows, mod_top, true,
info, &line_providers, &provider_err);
}
@@ -2359,7 +2358,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
// for ml_line_count+1 and only draw filler lines
foldinfo_T info = { 0 };
row = win_line(wp, wp->w_botline, row, wp->w_grid.rows,
- false, false, info, &line_providers, &provider_err);
+ mod_top, false, info, &line_providers, &provider_err);
}
} else if (dollar_vcol == -1) {
wp->w_botline = lnum;
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 2078fc4251..d6d5ff8ac7 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -53,6 +53,7 @@
#include "nvim/popupmenu.h"
#include "nvim/pos.h"
#include "nvim/search.h"
+#include "nvim/spell.h"
#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
@@ -232,7 +233,7 @@ static void insert_enter(InsertState *s)
stop_insert_mode = false;
// need to position cursor again when on a TAB
- if (gchar_cursor() == TAB) {
+ if (gchar_cursor() == TAB || curbuf->b_virt_text_inline > 0) {
curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
}
@@ -876,12 +877,12 @@ static int insert_handle_key(InsertState *s)
state_handle_k_event();
goto check_pum;
- case K_COMMAND: // some command
+ case K_COMMAND: // <Cmd>command<CR>
do_cmdline(NULL, getcmdkeycmd, NULL, 0);
goto check_pum;
case K_LUA:
- map_execute_lua();
+ map_execute_lua(false);
check_pum:
// nvim_select_popupmenu_item() can be called from the handling of
@@ -1526,10 +1527,11 @@ void edit_unputchar(void)
}
}
-// Called when p_dollar is set: display a '$' at the end of the changed text
-// Only works when cursor is in the line that changes.
-void display_dollar(colnr_T col)
+/// Called when "$" is in 'cpoptions': display a '$' at the end of the changed
+/// text. Only works when cursor is in the line that changes.
+void display_dollar(colnr_T col_arg)
{
+ colnr_T col = col_arg < 0 ? 0 : col_arg;
colnr_T save_col;
if (!redrawing()) {
@@ -2527,6 +2529,7 @@ int oneleft(void)
}
curwin->w_set_curswant = true;
+ adjust_skipcol();
return OK;
}
@@ -3469,7 +3472,7 @@ static bool ins_esc(long *count, int cmdchar, bool nomove)
State = MODE_NORMAL;
may_trigger_modechanged();
// need to position cursor again when on a TAB
- if (gchar_cursor() == TAB) {
+ if (gchar_cursor() == TAB || curbuf->b_virt_text_inline > 0) {
curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 13299b0253..52924bf9a5 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -3677,9 +3677,6 @@ static int eval_index_inner(typval_T *rettv, bool is_range, typval_T *var1, typv
} else if (n2 >= len) {
n2 = len;
}
- if (exclusive) {
- n2--;
- }
if (n1 >= len || n2 < 0 || n1 > n2) {
v = NULL;
} else {
@@ -4523,7 +4520,7 @@ bool garbage_collect(bool testing)
// Channels
{
Channel *data;
- map_foreach_value(&channels, data, {
+ pmap_foreach_value(&channels, data, {
set_ref_in_callback_reader(&data->on_data, copyID, NULL, NULL);
set_ref_in_callback_reader(&data->on_stderr, copyID, NULL, NULL);
set_ref_in_callback(&data->on_exit, copyID, NULL, NULL);
@@ -4533,7 +4530,7 @@ bool garbage_collect(bool testing)
// Timers
{
timer_T *timer;
- map_foreach_value(&timers, timer, {
+ pmap_foreach_value(&timers, timer, {
set_ref_in_callback(&timer->callback, copyID, NULL, NULL);
})
}
@@ -5989,7 +5986,7 @@ void add_timer_info_all(typval_T *rettv)
{
tv_list_alloc_ret(rettv, map_size(&timers));
timer_T *timer;
- map_foreach_value(&timers, timer, {
+ pmap_foreach_value(&timers, timer, {
if (!timer->stopped || timer->refcount > 1) {
add_timer_info(rettv, timer);
}
@@ -6087,7 +6084,7 @@ static void timer_close_cb(TimeWatcher *tw, void *data)
timer_T *timer = (timer_T *)data;
multiqueue_free(timer->tw.events);
callback_free(&timer->callback);
- pmap_del(uint64_t)(&timers, (uint64_t)timer->timer_id);
+ pmap_del(uint64_t)(&timers, (uint64_t)timer->timer_id, NULL);
timer_decref(timer);
}
@@ -6101,7 +6098,7 @@ static void timer_decref(timer_T *timer)
void timer_stop_all(void)
{
timer_T *timer;
- map_foreach_value(&timers, timer, {
+ pmap_foreach_value(&timers, timer, {
timer_stop(timer);
})
}
@@ -8657,7 +8654,7 @@ bool eval_has_provider(const char *feat)
return false;
}
- char name[32]; // Normalized: "python_compiled" => "python".
+ char name[32]; // Normalized: "python3_compiled" => "python3".
snprintf(name, sizeof(name), "%s", feat);
strchrsub(name, '_', '\0'); // Chop any "_xx" suffix.
@@ -8715,7 +8712,7 @@ void ex_checkhealth(exarg_T *eap)
{
Error err = ERROR_INIT;
MAXSIZE_TEMP_ARRAY(args, 1);
- ADD_C(args, STRING_OBJ(cstr_as_string(eap->arg)));
+ ADD_C(args, CSTR_AS_OBJ(eap->arg));
NLUA_EXEC_STATIC("return vim.health._check(...)", args, &err);
if (!ERROR_SET(&err)) {
return;
diff --git a/src/nvim/eval/decode.h b/src/nvim/eval/decode.h
index f1be5a1f69..7455130221 100644
--- a/src/nvim/eval/decode.h
+++ b/src/nvim/eval/decode.h
@@ -4,8 +4,8 @@
#include <msgpack.h>
#include <stddef.h>
-#include "nvim/eval/typval.h"
-#include "nvim/globals.h"
+#include "nvim/eval/typval_defs.h"
+#include "nvim/types.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/decode.h.generated.h"
diff --git a/src/nvim/eval/executor.h b/src/nvim/eval/executor.h
index 42abf77f4a..e8bf147245 100644
--- a/src/nvim/eval/executor.h
+++ b/src/nvim/eval/executor.h
@@ -1,7 +1,7 @@
#ifndef NVIM_EVAL_EXECUTOR_H
#define NVIM_EVAL_EXECUTOR_H
-#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
extern char *e_list_index_out_of_range_nr;
diff --git a/src/nvim/eval/funcs.h b/src/nvim/eval/funcs.h
index 1ae031a952..65a95196de 100644
--- a/src/nvim/eval/funcs.h
+++ b/src/nvim/eval/funcs.h
@@ -6,7 +6,6 @@
#include "nvim/api/private/dispatch.h"
#include "nvim/buffer_defs.h"
-#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/types.h"
diff --git a/src/nvim/eval/gc.h b/src/nvim/eval/gc.h
index 3185750c3b..66e959ced5 100644
--- a/src/nvim/eval/gc.h
+++ b/src/nvim/eval/gc.h
@@ -1,7 +1,6 @@
#ifndef NVIM_EVAL_GC_H
#define NVIM_EVAL_GC_H
-#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
extern dict_T *gc_first_dict;
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index 5755178b18..cb8f8ce44d 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -2166,6 +2166,16 @@ varnumber_T tv_dict_get_number_def(const dict_T *const d, const char *const key,
return tv_get_number(&di->di_tv);
}
+varnumber_T tv_dict_get_bool(const dict_T *const d, const char *const key, const int def)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ dictitem_T *const di = tv_dict_find(d, key, -1);
+ if (di == NULL) {
+ return def;
+ }
+ return tv_get_bool(&di->di_tv);
+}
+
/// Converts a dict to an environment
char **tv_dict_to_env(dict_T *denv)
{
@@ -4049,6 +4059,18 @@ varnumber_T tv_get_number_chk(const typval_T *const tv, bool *const ret_error)
return (ret_error == NULL ? -1 : 0);
}
+varnumber_T tv_get_bool(const typval_T *const tv)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return tv_get_number_chk(tv, NULL);
+}
+
+varnumber_T tv_get_bool_chk(const typval_T *const tv, bool *const ret_error)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1)
+{
+ return tv_get_number_chk(tv, ret_error);
+}
+
/// Get the line number from VimL object
///
/// @param[in] tv Object to get value from. Is expected to be a number or
diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h
index 84e4067f9d..767fd706b3 100644
--- a/src/nvim/eval/typval.h
+++ b/src/nvim/eval/typval.h
@@ -567,8 +567,4 @@ EXTERN const size_t kTVTranslate INIT(= TV_TRANSLATE);
# include "eval/typval.h.generated.h"
#endif
-#define tv_get_bool tv_get_number
-#define tv_get_bool_chk tv_get_number_chk
-#define tv_dict_get_bool tv_dict_get_number_def
-
#endif // NVIM_EVAL_TYPVAL_H
diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h
index 2f19144da3..171b0417d0 100644
--- a/src/nvim/eval/typval_encode.h
+++ b/src/nvim/eval/typval_encode.h
@@ -11,7 +11,7 @@
#include <string.h>
#include "klib/kvec.h"
-#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/func_attr.h"
/// Type of the stack entry
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index fbb5e8d10c..a52b8d3f18 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -467,12 +467,10 @@ char *deref_func_name(const char *name, int *lenp, partial_T **const partialp, b
/// @param name function name
void emsg_funcname(const char *errmsg, const char *name)
{
- char *p;
+ char *p = (char *)name;
- if ((uint8_t)(*name) == K_SPECIAL) {
+ if ((uint8_t)name[0] == K_SPECIAL && name[1] != NUL && name[2] != NUL) {
p = concat_str("<SNR>", name + 3);
- } else {
- p = (char *)name;
}
semsg(_(errmsg), p);
@@ -1863,8 +1861,7 @@ char *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, part
// Check for hard coded <SNR>: already translated function ID (from a user
// command).
- if ((unsigned char)(*pp)[0] == K_SPECIAL && (unsigned char)(*pp)[1] == KS_EXTRA
- && (*pp)[2] == KE_SNR) {
+ if ((uint8_t)(*pp)[0] == K_SPECIAL && (uint8_t)(*pp)[1] == KS_EXTRA && (*pp)[2] == KE_SNR) {
*pp += 3;
len = get_id_len((const char **)pp) + 3;
return xmemdupz(start, (size_t)len);
@@ -2140,7 +2137,6 @@ void ex_function(exarg_T *eap)
char *theline;
char *line_to_free = NULL;
char c;
- int saved_did_emsg;
bool saved_wait_return = need_wait_return;
char *name = NULL;
char *p;
@@ -2234,7 +2230,7 @@ void ex_function(exarg_T *eap)
// An error in a function call during evaluation of an expression in magic
// braces should not cause the function not to be defined.
- saved_did_emsg = did_emsg;
+ const int saved_did_emsg = did_emsg;
did_emsg = false;
//
@@ -2896,9 +2892,9 @@ char *get_user_func_name(expand_T *xp, int idx)
cat_func_name(IObuff, IOSIZE, fp);
if (xp->xp_context != EXPAND_USER_FUNC) {
- STRCAT(IObuff, "(");
+ xstrlcat(IObuff, "(", IOSIZE);
if (!fp->uf_varargs && GA_EMPTY(&fp->uf_args)) {
- STRCAT(IObuff, ")");
+ xstrlcat(IObuff, ")", IOSIZE);
}
}
return IObuff;
@@ -3509,7 +3505,7 @@ char *get_return_cmd(void *rettv)
s = "";
}
- STRCPY(IObuff, ":return ");
+ xstrlcpy(IObuff, ":return ", IOSIZE);
xstrlcpy(IObuff + 8, s, IOSIZE - 8);
if (strlen(s) + 8 >= IOSIZE) {
STRCPY(IObuff + IOSIZE - 4, "...");
diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h
index 4a98afb00e..562c549b4b 100644
--- a/src/nvim/eval/userfunc.h
+++ b/src/nvim/eval/userfunc.h
@@ -5,7 +5,6 @@
#include <stddef.h>
#include "nvim/eval.h"
-#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/garray.h"
diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h
index e0057faffb..39fed08c77 100644
--- a/src/nvim/event/process.h
+++ b/src/nvim/event/process.h
@@ -5,7 +5,6 @@
#include <stddef.h>
#include <stdint.h>
-#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index dbfd1088d2..1d8c3c0cf4 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -54,7 +54,6 @@
#include "nvim/highlight_group.h"
#include "nvim/indent.h"
#include "nvim/input.h"
-#include "nvim/lua/executor.h"
#include "nvim/macros.h"
#include "nvim/main.h"
#include "nvim/mark.h"
@@ -1926,6 +1925,9 @@ void do_wqall(exarg_T *eap)
int save_forceit = eap->forceit;
if (eap->cmdidx == CMD_xall || eap->cmdidx == CMD_wqall) {
+ if (before_quit_all(eap) == FAIL) {
+ return;
+ }
exiting = true;
}
@@ -4801,29 +4803,3 @@ void ex_oldfiles(exarg_T *eap)
}
}
}
-
-void ex_trust(exarg_T *eap)
-{
- const char *const p = skiptowhite(eap->arg);
- char *arg1 = xmemdupz(eap->arg, (size_t)(p - eap->arg));
- const char *action = "allow";
- const char *path = skipwhite(p);
-
- if (strcmp(arg1, "++deny") == 0) {
- action = "deny";
- } else if (strcmp(arg1, "++remove") == 0) {
- action = "remove";
- } else if (*arg1 != '\0') {
- semsg(e_invarg2, arg1);
- goto theend;
- }
-
- if (path[0] == '\0') {
- path = NULL;
- }
-
- nlua_trust(action, path);
-
-theend:
- xfree(arg1);
-}
diff --git a/src/nvim/ex_cmds.h b/src/nvim/ex_cmds.h
index 39bff3e35d..148065e096 100644
--- a/src/nvim/ex_cmds.h
+++ b/src/nvim/ex_cmds.h
@@ -4,7 +4,6 @@
#include <stdbool.h>
#include "nvim/buffer_defs.h"
-#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/os/time.h"
diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h
index 2acedb5ec3..568d4d38ba 100644
--- a/src/nvim/ex_cmds_defs.h
+++ b/src/nvim/ex_cmds_defs.h
@@ -4,7 +4,7 @@
#include <stdbool.h>
#include <stdint.h>
-#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/normal.h"
#include "nvim/pos.h"
#include "nvim/regexp_defs.h"
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index adb17f2cfd..9666d80de2 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -1454,7 +1454,7 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
}
// Fail if command is invalid
if (eap->cmdidx == CMD_SIZE) {
- STRCPY(IObuff, _(e_not_an_editor_command));
+ xstrlcpy(IObuff, _(e_not_an_editor_command), IOSIZE);
// If the modifier was parsed OK the error must be in the following command
char *cmdname = after_modifier ? after_modifier : cmdline;
append_command(cmdname);
@@ -2044,7 +2044,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
// Check for wrong commands.
if (ea.cmdidx == CMD_SIZE) {
if (!ea.skip) {
- STRCPY(IObuff, _(e_not_an_editor_command));
+ xstrlcpy(IObuff, _(e_not_an_editor_command), IOSIZE);
// If the modifier was parsed OK the error must be in the following
// command
char *cmdname = after_modifier ? after_modifier : *cmdlinep;
@@ -2321,7 +2321,7 @@ doend:
if (errormsg != NULL && *errormsg != NUL && !did_emsg) {
if (flags & DOCMD_VERBOSE) {
if (errormsg != IObuff) {
- STRCPY(IObuff, errormsg);
+ xstrlcpy(IObuff, errormsg, IOSIZE);
errormsg = IObuff;
}
append_command(*ea.cmdlinep);
@@ -2888,7 +2888,7 @@ static void append_command(char *cmd)
d -= utf_head_off(IObuff, d);
STRCPY(d, "...");
}
- STRCAT(IObuff, ": ");
+ xstrlcat(IObuff, ": ", IOSIZE);
d = IObuff + strlen(IObuff);
while (*s != NUL && d - IObuff + 5 < IOSIZE) {
if ((uint8_t)s[0] == 0xc2 && (uint8_t)s[1] == 0xa0) {
@@ -4589,8 +4589,9 @@ static void ex_cquit(exarg_T *eap)
getout(eap->addr_count > 0 ? (int)eap->line2 : EXIT_FAILURE);
}
-/// ":qall": try to quit all windows
-static void ex_quit_all(exarg_T *eap)
+/// Do preparations for "qall" and "wqall".
+/// Returns FAIL when quitting should be aborted.
+int before_quit_all(exarg_T *eap)
{
if (cmdwin_type != 0) {
if (eap->forceit) {
@@ -4598,19 +4599,28 @@ static void ex_quit_all(exarg_T *eap)
} else {
cmdwin_result = K_XF2;
}
- return;
+ return FAIL;
}
// Don't quit while editing the command line.
if (text_locked()) {
text_locked_msg();
- return;
+ return FAIL;
}
if (before_quit_autocmds(curwin, true, eap->forceit)) {
- return;
+ return FAIL;
}
+ return OK;
+}
+
+/// ":qall": try to quit all windows
+static void ex_quit_all(exarg_T *eap)
+{
+ if (before_quit_all(eap) == FAIL) {
+ return;
+ }
exiting = true;
if (eap->forceit || !check_changed_any(false, false)) {
getout(0);
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index af2ec3356f..dd23f6ece9 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -127,6 +127,7 @@ typedef struct command_line_state {
int break_ctrl_c;
expand_T xpc;
long *b_im_ptr;
+ buf_T *b_im_ptr_buf; ///< buffer where b_im_ptr is valid
} CommandLineState;
typedef struct cmdpreview_win_info {
@@ -736,7 +737,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool clea
} else {
s->b_im_ptr = &curbuf->b_p_imsearch;
}
-
+ s->b_im_ptr_buf = curbuf;
if (*s->b_im_ptr == B_IMODE_LMAP) {
State |= MODE_LANGMAP;
}
@@ -1140,7 +1141,7 @@ static int command_line_execute(VimState *state, int key)
} else if (s->c == K_COMMAND) {
do_cmdline(NULL, getcmdkeycmd, NULL, DOCMD_NOWAIT);
} else {
- map_execute_lua();
+ map_execute_lua(false);
}
// nvim_select_popupmenu_item() can be called from the handling of
@@ -1538,20 +1539,21 @@ static int command_line_erase_chars(CommandLineState *s)
/// language :lmap mappings and/or Input Method.
static void command_line_toggle_langmap(CommandLineState *s)
{
+ long *b_im_ptr = buf_valid(s->b_im_ptr_buf) ? s->b_im_ptr : NULL;
if (map_to_exists_mode("", MODE_LANGMAP, false)) {
// ":lmap" mappings exists, toggle use of mappings.
State ^= MODE_LANGMAP;
- if (s->b_im_ptr != NULL) {
+ if (b_im_ptr != NULL) {
if (State & MODE_LANGMAP) {
- *s->b_im_ptr = B_IMODE_LMAP;
+ *b_im_ptr = B_IMODE_LMAP;
} else {
- *s->b_im_ptr = B_IMODE_NONE;
+ *b_im_ptr = B_IMODE_NONE;
}
}
}
- if (s->b_im_ptr != NULL) {
- if (s->b_im_ptr == &curbuf->b_p_iminsert) {
+ if (b_im_ptr != NULL) {
+ if (b_im_ptr == &curbuf->b_p_iminsert) {
set_iminsert_global(curbuf);
} else {
set_imsearch_global(curbuf);
@@ -3385,7 +3387,7 @@ static void ui_ext_cmdline_show(CmdlineInfo *line)
} else {
Array item = arena_array(&arena, 2);
ADD_C(item, INTEGER_OBJ(0));
- ADD_C(item, STRING_OBJ(cstr_as_string(line->cmdbuff)));
+ ADD_C(item, CSTR_AS_OBJ(line->cmdbuff));
content = arena_array(&arena, 1);
ADD_C(content, ARRAY_OBJ(item));
}
@@ -3412,7 +3414,7 @@ void ui_ext_cmdline_block_append(size_t indent, const char *line)
Array item = ARRAY_DICT_INIT;
ADD(item, INTEGER_OBJ(0));
- ADD(item, STRING_OBJ(cstr_as_string(buf)));
+ ADD(item, CSTR_AS_OBJ(buf));
Array content = ARRAY_DICT_INIT;
ADD(content, ARRAY_OBJ(item));
ADD(cmdline_block, ARRAY_OBJ(content));
diff --git a/src/nvim/ex_getln.h b/src/nvim/ex_getln.h
index 61ac4b69c5..b21fb0506d 100644
--- a/src/nvim/ex_getln.h
+++ b/src/nvim/ex_getln.h
@@ -4,7 +4,6 @@
#include <stdbool.h>
#include "klib/kvec.h"
-#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/types.h"
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index 727be1562c..f4a6a02682 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -50,11 +50,6 @@
# include "extmark.c.generated.h"
#endif
-static uint32_t *buf_ns_ref(buf_T *buf, uint32_t ns_id, bool put)
-{
- return map_ref(uint32_t, uint32_t)(buf->b_extmark_ns, ns_id, put);
-}
-
/// Create or update an extmark
///
/// must not be used during iteration!
@@ -62,7 +57,7 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
colnr_T end_col, Decoration *decor, bool right_gravity, bool end_right_gravity,
ExtmarkOp op, Error *err)
{
- uint32_t *ns = buf_ns_ref(buf, ns_id, true);
+ uint32_t *ns = map_put_ref(uint32_t, uint32_t)(buf->b_extmark_ns, ns_id, NULL, NULL);
uint32_t id = idp ? *idp : 0;
bool decor_full = false;
@@ -153,6 +148,9 @@ revised:
}
if (decor) {
+ if (kv_size(decor->virt_text) && decor->virt_text_pos == kVTInline) {
+ buf->b_virt_text_inline++;
+ }
if (kv_size(decor->virt_lines)) {
buf->b_virt_line_blocks++;
}
@@ -237,7 +235,7 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r
bool all_ns = (ns_id == 0);
uint32_t *ns = NULL;
if (!all_ns) {
- ns = buf_ns_ref(buf, ns_id, false);
+ ns = map_ref(uint32_t, uint32_t)(buf->b_extmark_ns, ns_id, NULL);
if (!ns) {
// nothing to do
return false;
@@ -258,15 +256,14 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r
|| (mark.pos.row == u_row && mark.pos.col > u_col)) {
break;
}
- ssize_t *del_status = map_ref(uint64_t, ssize_t)(&delete_set, mt_lookup_key(mark),
- false);
+ ssize_t *del_status = map_ref(uint64_t, ssize_t)(&delete_set, mt_lookup_key(mark), NULL);
if (del_status) {
marktree_del_itr(buf->b_marktree, itr, false);
if (*del_status >= 0) { // we had a decor_id
DecorItem it = kv_A(decors, *del_status);
decor_remove(buf, it.row1, mark.pos.row, mark.decor_full);
}
- map_del(uint64_t, ssize_t)(&delete_set, mt_lookup_key(mark));
+ map_del(uint64_t, ssize_t)(&delete_set, mt_lookup_key(mark), NULL);
continue;
}
@@ -294,7 +291,7 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r
}
uint64_t id;
ssize_t decor_id;
- map_foreach(&delete_set, id, decor_id, {
+ map_foreach(ssize_t, &delete_set, id, decor_id, {
mtkey_t mark = marktree_lookup(buf->b_marktree, id, itr);
assert(marktree_itr_valid(itr));
marktree_del_itr(buf->b_marktree, itr, false);
@@ -303,7 +300,7 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r
decor_remove(buf, it.row1, mark.pos.row, mark.decor_full);
}
});
- map_clear(uint64_t, ssize_t)(&delete_set);
+ map_clear(uint64_t, &delete_set);
kv_size(decors) = 0;
return marks_cleared;
}
@@ -424,8 +421,8 @@ void extmark_free_all(buf_T *buf)
marktree_clear(buf->b_marktree);
- map_destroy(uint32_t, uint32_t)(buf->b_extmark_ns);
- map_init(uint32_t, uint32_t, buf->b_extmark_ns);
+ map_destroy(uint32_t, buf->b_extmark_ns);
+ *buf->b_extmark_ns = (Map(uint32_t, uint32_t)) MAP_INIT;
}
/// Save info for undo/redo of set marks
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index d659987686..e60007bf88 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -1693,22 +1693,22 @@ failed:
#ifdef UNIX
if (S_ISFIFO(perm)) { // fifo
- STRCAT(IObuff, _("[fifo]"));
+ xstrlcat(IObuff, _("[fifo]"), IOSIZE);
c = true;
}
if (S_ISSOCK(perm)) { // or socket
- STRCAT(IObuff, _("[socket]"));
+ xstrlcat(IObuff, _("[socket]"), IOSIZE);
c = true;
}
# ifdef OPEN_CHR_FILES
if (S_ISCHR(perm)) { // or character special
- STRCAT(IObuff, _("[character special]"));
+ xstrlcat(IObuff, _("[character special]"), IOSIZE);
c = true;
}
# endif
#endif
if (curbuf->b_p_ro) {
- STRCAT(IObuff, shortmess(SHM_RO) ? _("[RO]") : _("[readonly]"));
+ xstrlcat(IObuff, shortmess(SHM_RO) ? _("[RO]") : _("[readonly]"), IOSIZE);
c = true;
}
if (read_no_eol_lnum) {
@@ -1716,18 +1716,18 @@ failed:
c = true;
}
if (ff_error == EOL_DOS) {
- STRCAT(IObuff, _("[CR missing]"));
+ xstrlcat(IObuff, _("[CR missing]"), IOSIZE);
c = true;
}
if (split) {
- STRCAT(IObuff, _("[long lines split]"));
+ xstrlcat(IObuff, _("[long lines split]"), IOSIZE);
c = true;
}
if (notconverted) {
- STRCAT(IObuff, _("[NOT converted]"));
+ xstrlcat(IObuff, _("[NOT converted]"), IOSIZE);
c = true;
} else if (converted) {
- STRCAT(IObuff, _("[converted]"));
+ xstrlcat(IObuff, _("[converted]"), IOSIZE);
c = true;
}
if (conv_error != 0) {
@@ -1739,7 +1739,7 @@ failed:
_("[ILLEGAL BYTE in line %" PRId64 "]"), (int64_t)illegal_byte);
c = true;
} else if (error) {
- STRCAT(IObuff, _("[READ ERRORS]"));
+ xstrlcat(IObuff, _("[READ ERRORS]"), IOSIZE);
c = true;
}
if (msg_add_fileformat(fileformat)) {
@@ -2128,17 +2128,17 @@ bool msg_add_fileformat(int eol_type)
{
#ifndef USE_CRNL
if (eol_type == EOL_DOS) {
- STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[dos]") : _("[dos format]"));
+ xstrlcat(IObuff, shortmess(SHM_TEXT) ? _("[dos]") : _("[dos format]"), IOSIZE);
return true;
}
#endif
if (eol_type == EOL_MAC) {
- STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[mac]") : _("[mac format]"));
+ xstrlcat(IObuff, shortmess(SHM_TEXT) ? _("[mac]") : _("[mac format]"), IOSIZE);
return true;
}
#ifdef USE_CRNL
if (eol_type == EOL_UNIX) {
- STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[unix]") : _("[unix format]"));
+ xstrlcat(IObuff, shortmess(SHM_TEXT) ? _("[unix]") : _("[unix format]"), IOSIZE);
return true;
}
#endif
@@ -2170,8 +2170,7 @@ void msg_add_lines(int insert_space, long lnum, off_T nchars)
/// Append message for missing line separator to IObuff.
void msg_add_eol(void)
{
- STRCAT(IObuff,
- shortmess(SHM_LAST) ? _("[noeol]") : _("[Incomplete last line]"));
+ xstrlcat(IObuff, shortmess(SHM_LAST) ? _("[noeol]") : _("[Incomplete last line]"), IOSIZE);
}
bool time_differs(const FileInfo *file_info, long mtime, long mtime_ns) FUNC_ATTR_CONST
@@ -3482,8 +3481,7 @@ void vim_deltempdir(void)
char *vim_gettempdir(void)
{
static int notfound = 0;
- bool exists = false;
- if (vim_tempdir == NULL || !(exists = os_isdir(vim_tempdir))) {
+ if (vim_tempdir == NULL || !os_isdir(vim_tempdir)) {
if (vim_tempdir != NULL) {
notfound++;
if (notfound == 1) {
diff --git a/src/nvim/fileio.h b/src/nvim/fileio.h
index a4566d754b..5eb2689233 100644
--- a/src/nvim/fileio.h
+++ b/src/nvim/fileio.h
@@ -2,7 +2,6 @@
#define NVIM_FILEIO_H
#include "nvim/buffer_defs.h"
-#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/garray.h"
#include "nvim/os/os.h"
diff --git a/src/nvim/generators/gen_ex_cmds.lua b/src/nvim/generators/gen_ex_cmds.lua
index 76b372eac2..b9fae7d0fe 100644
--- a/src/nvim/generators/gen_ex_cmds.lua
+++ b/src/nvim/generators/gen_ex_cmds.lua
@@ -55,6 +55,7 @@ defsfile:write(string.format([[
#include "nvim/help.h"
#include "nvim/indent.h"
#include "nvim/lua/executor.h"
+#include "nvim/lua/secure.h"
#include "nvim/mapping.h"
#include "nvim/mark.h"
#include "nvim/match.h"
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index a0e8350287..5c1366c5b2 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -92,8 +92,8 @@ static buffheader_T readbuf2 = { { NULL, { NUL } }, NULL, 0, 0 };
static int typeahead_char = 0; // typeahead char that's not flushed
-// when block_redo is true redo buffer will not be changed
-// used by edit() to repeat insertions and 'V' command for redoing
+/// When block_redo is true the redo buffer will not be changed.
+/// Used by edit() to repeat insertions.
static int block_redo = false;
static int KeyNoremap = 0; // remapping flags
@@ -134,6 +134,10 @@ static size_t last_recorded_len = 0; // number of last recorded chars
#endif
static const char e_recursive_mapping[] = N_("E223: Recursive mapping");
+static const char e_cmd_mapping_must_end_with_cr[]
+ = N_("E1255: <Cmd> mapping must end with <CR>");
+static const char e_cmd_mapping_must_end_with_cr_before_second_cmd[]
+ = N_("E1136: <Cmd> mapping must end with <CR> before second <Cmd>");
// Free and clear a buffer.
void free_buff(buffheader_T *buf)
@@ -550,6 +554,25 @@ void AppendToRedobuffLit(const char *str, int len)
}
}
+/// Append "s" to the redo buffer, leaving 3-byte special key codes unmodified
+/// and escaping other K_SPECIAL bytes.
+void AppendToRedobuffSpec(const char *s)
+{
+ if (block_redo) {
+ return;
+ }
+
+ while (*s != NUL) {
+ if ((uint8_t)(*s) == K_SPECIAL && s[1] != NUL && s[2] != NUL) {
+ // Insert special key literally.
+ add_buff(&redobuff, s, 3L);
+ s += 3;
+ } else {
+ add_char_buff(&redobuff, mb_cptr2char_adv(&s));
+ }
+ }
+}
+
/// Append a character to the redo buffer.
/// Translates special keys, NUL, K_SPECIAL and multibyte characters.
void AppendCharToRedobuff(int c)
@@ -2884,7 +2907,8 @@ int fix_input_buffer(uint8_t *buf, int len)
return len;
}
-/// Get command argument for <Cmd> key
+/// Function passed to do_cmdline() to get the command after a <Cmd> key from
+/// typeahead.
char *getcmdkeycmd(int promptc, void *cookie, int indent, bool do_concat)
{
garray_T line_ga;
@@ -2894,6 +2918,7 @@ char *getcmdkeycmd(int promptc, void *cookie, int indent, bool do_concat)
ga_init(&line_ga, 1, 32);
+ // no mapping for these characters
no_mapping++;
got_int = false;
@@ -2903,16 +2928,17 @@ char *getcmdkeycmd(int promptc, void *cookie, int indent, bool do_concat)
if (vgetorpeek(false) == NUL) {
// incomplete <Cmd> is an error, because there is not much the user
// could do in this state.
- emsg(e_cmdmap_err);
+ emsg(_(e_cmd_mapping_must_end_with_cr));
aborted = true;
break;
}
// Get one character at a time.
c1 = vgetorpeek(true);
+
// Get two extra bytes for special keys
if (c1 == K_SPECIAL) {
- c1 = vgetorpeek(true); // no mapping for these chars
+ c1 = vgetorpeek(true);
c2 = vgetorpeek(true);
if (c1 == KS_MODIFIER) {
cmod = c2;
@@ -2928,8 +2954,8 @@ char *getcmdkeycmd(int promptc, void *cookie, int indent, bool do_concat)
} else if (c1 == ESC) {
aborted = true;
} else if (c1 == K_COMMAND) {
- // special case to give nicer error message
- emsg(e_cmdmap_repeated);
+ // give a nicer error message for this special case
+ emsg(_(e_cmd_mapping_must_end_with_cr_before_second_cmd));
aborted = true;
} else if (c1 == K_SNR) {
ga_concat(&line_ga, "<SNR>");
@@ -2960,7 +2986,12 @@ char *getcmdkeycmd(int promptc, void *cookie, int indent, bool do_concat)
return line_ga.ga_data;
}
-bool map_execute_lua(void)
+/// Handle a Lua mapping: get its LuaRef from typeahead and execute it.
+///
+/// @param may_repeat save the LuaRef for redoing with "." later
+///
+/// @return false if getting the LuaRef was aborted, true otherwise
+bool map_execute_lua(bool may_repeat)
{
garray_T line_ga;
int c1 = -1;
@@ -2992,6 +3023,10 @@ bool map_execute_lua(void)
}
LuaRef ref = (LuaRef)atoi(line_ga.ga_data);
+ if (may_repeat) {
+ repeat_luaref = ref;
+ }
+
Error err = ERROR_INIT;
Array args = ARRAY_DICT_INIT;
nlua_call_ref(ref, NULL, args, false, &err);
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 698f4a98c7..bedb529d04 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -993,7 +993,8 @@ EXTERN const char e_notset[] INIT(= N_("E764: Option '%s' is not set"));
EXTERN const char e_invalidreg[] INIT(= N_("E850: Invalid register name"));
EXTERN const char e_dirnotf[] INIT(= N_("E919: Directory not found in '%s': \"%s\""));
EXTERN const char e_au_recursive[] INIT(= N_("E952: Autocommand caused recursive behavior"));
-EXTERN const char e_menuothermode[] INIT(= N_("E328: Menu only exists in another mode"));
+EXTERN const char e_menu_only_exists_in_another_mode[]
+INIT(= N_("E328: Menu only exists in another mode"));
EXTERN const char e_autocmd_close[] INIT(= N_("E813: Cannot close autocmd window"));
EXTERN const char e_listarg[] INIT(= N_("E686: Argument of %s must be a List"));
EXTERN const char e_unsupportedoption[] INIT(= N_("E519: Option not supported"));
@@ -1003,10 +1004,6 @@ EXTERN const char e_cannot_edit_other_buf[] INIT(= N_("E788: Not allowed to edit
EXTERN const char e_using_number_as_bool_nr[] INIT(= N_("E1023: Using a Number as a Bool: %d"));
EXTERN const char e_not_callable_type_str[] INIT(= N_("E1085: Not a callable type: %s"));
-EXTERN const char e_cmdmap_err[] INIT(= N_("E5520: <Cmd> mapping must end with <CR>"));
-EXTERN const char e_cmdmap_repeated[]
-INIT(= N_("E5521: <Cmd> mapping must end with <CR> before second <Cmd>"));
-
EXTERN const char e_api_error[] INIT(= N_("E5555: API call: %s"));
EXTERN const char e_luv_api_disabled[] INIT(= N_("E5560: %s must not be called in a lua loop callback"));
diff --git a/src/nvim/grid.c b/src/nvim/grid.c
index 037606c38f..76dd2a073a 100644
--- a/src/nvim/grid.c
+++ b/src/nvim/grid.c
@@ -316,8 +316,7 @@ int grid_puts_len(ScreenGrid *grid, const char *text, int textlen, int row, int
// When at the start of the text and overwriting the right half of a
// two-cell character in the same grid, truncate that into a '>'.
if (ptr == text && col > 0 && grid->chars[off][0] == 0) {
- grid->chars[off - 1][0] = '>';
- grid->chars[off - 1][1] = 0;
+ schar_from_ascii(grid->chars[off - 1], '>');
}
schar_copy(grid->chars[off], buf);
diff --git a/src/nvim/help.c b/src/nvim/help.c
index 633e9df244..d412f3a098 100644
--- a/src/nvim/help.c
+++ b/src/nvim/help.c
@@ -22,6 +22,7 @@
#include "nvim/globals.h"
#include "nvim/help.h"
#include "nvim/macros.h"
+#include "nvim/mark.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c
index e2f3e2aafa..fad113adc5 100644
--- a/src/nvim/highlight.c
+++ b/src/nvim/highlight.c
@@ -50,7 +50,7 @@ static Map(int, int) blendthrough_attr_entries = MAP_INIT;
/// highlight entries private to a namespace
static Map(ColorKey, ColorItem) ns_hls;
typedef int NSHlAttr[HLF_COUNT + 1];
-static PMap(handle_T) ns_hl_attr;
+static PMap(int) ns_hl_attr;
void highlight_init(void)
{
@@ -207,7 +207,7 @@ int ns_get_hl(NS *ns_hl, int hl_id, bool link, bool nodefault)
if (!valid_item && p->hl_def != LUA_NOREF && !recursive) {
MAXSIZE_TEMP_ARRAY(args, 3);
ADD_C(args, INTEGER_OBJ((Integer)ns_id));
- ADD_C(args, STRING_OBJ(cstr_to_string(syn_id2name(hl_id))));
+ ADD_C(args, CSTR_TO_OBJ(syn_id2name(hl_id)));
ADD_C(args, BOOLEAN_OBJ(link));
// TODO(bfredl): preload the "global" attr dict?
@@ -277,7 +277,7 @@ bool hl_check_ns(void)
hl_attr_active = highlight_attr;
if (ns > 0) {
update_ns_hl(ns);
- NSHlAttr *hl_def = (NSHlAttr *)pmap_get(handle_T)(&ns_hl_attr, ns);
+ NSHlAttr *hl_def = (NSHlAttr *)pmap_get(int)(&ns_hl_attr, ns);
if (hl_def) {
hl_attr_active = *hl_def;
}
@@ -335,7 +335,7 @@ void update_window_hl(win_T *wp, bool invalid)
if (ns_id != wp->w_ns_hl_active || wp->w_ns_hl_attr == NULL) {
wp->w_ns_hl_active = ns_id;
- wp->w_ns_hl_attr = *(NSHlAttr *)pmap_get(handle_T)(&ns_hl_attr, ns_id);
+ wp->w_ns_hl_attr = *(NSHlAttr *)pmap_get(int)(&ns_hl_attr, ns_id);
if (!wp->w_ns_hl_attr) {
// No specific highlights, use the defaults.
wp->w_ns_hl_attr = highlight_attr;
@@ -398,6 +398,15 @@ void update_window_hl(win_T *wp, bool invalid)
} else {
wp->w_hl_attr_normalnc = hl_def[HLF_INACTIVE];
}
+
+ // if blend= attribute is not set, 'winblend' value overrides it.
+ if (wp->w_floating && wp->w_p_winbl > 0) {
+ HlEntry entry = kv_A(attr_entries, wp->w_hl_attr_normalnc);
+ if (entry.attr.hl_blend == -1) {
+ entry.attr.hl_blend = (int)wp->w_p_winbl;
+ wp->w_hl_attr_normalnc = get_attr_entry(entry);
+ }
+ }
}
void update_ns_hl(int ns_id)
@@ -410,7 +419,7 @@ void update_ns_hl(int ns_id)
return;
}
- NSHlAttr **alloc = (NSHlAttr **)pmap_ref(handle_T)(&ns_hl_attr, ns_id, true);
+ NSHlAttr **alloc = (NSHlAttr **)pmap_put_ref(int)(&ns_hl_attr, ns_id, NULL, NULL);
if (*alloc == NULL) {
*alloc = xmalloc(sizeof(**alloc));
}
@@ -482,28 +491,28 @@ void clear_hl_tables(bool reinit)
{
if (reinit) {
kv_size(attr_entries) = 1;
- map_clear(HlEntry, int)(&attr_entry_ids);
- map_clear(int, int)(&combine_attr_entries);
- map_clear(int, int)(&blend_attr_entries);
- map_clear(int, int)(&blendthrough_attr_entries);
+ map_clear(HlEntry, &attr_entry_ids);
+ map_clear(int, &combine_attr_entries);
+ map_clear(int, &blend_attr_entries);
+ map_clear(int, &blendthrough_attr_entries);
memset(highlight_attr_last, -1, sizeof(highlight_attr_last));
highlight_attr_set_all();
highlight_changed();
screen_invalidate_highlights();
} else {
kv_destroy(attr_entries);
- map_destroy(HlEntry, int)(&attr_entry_ids);
- map_destroy(int, int)(&combine_attr_entries);
- map_destroy(int, int)(&blend_attr_entries);
- map_destroy(int, int)(&blendthrough_attr_entries);
- map_destroy(ColorKey, ColorItem)(&ns_hls);
+ map_destroy(HlEntry, &attr_entry_ids);
+ map_destroy(int, &combine_attr_entries);
+ map_destroy(int, &blend_attr_entries);
+ map_destroy(int, &blendthrough_attr_entries);
+ map_destroy(ColorKey, &ns_hls);
}
}
void hl_invalidate_blends(void)
{
- map_clear(int, int)(&blend_attr_entries);
- map_clear(int, int)(&blendthrough_attr_entries);
+ map_clear(int, &blend_attr_entries);
+ map_clear(int, &blendthrough_attr_entries);
highlight_changed();
update_window_hl(curwin, true);
}
@@ -1132,21 +1141,21 @@ static void hl_inspect_impl(Array *arr, int attr)
HlEntry e = kv_A(attr_entries, attr);
switch (e.kind) {
case kHlSyntax:
- PUT(item, "kind", STRING_OBJ(cstr_to_string("syntax")));
+ PUT(item, "kind", CSTR_TO_OBJ("syntax"));
PUT(item, "hi_name",
- STRING_OBJ(cstr_to_string(syn_id2name(e.id1))));
+ CSTR_TO_OBJ(syn_id2name(e.id1)));
break;
case kHlUI:
- PUT(item, "kind", STRING_OBJ(cstr_to_string("ui")));
+ PUT(item, "kind", CSTR_TO_OBJ("ui"));
const char *ui_name = (e.id1 == -1) ? "Normal" : hlf_names[e.id1];
- PUT(item, "ui_name", STRING_OBJ(cstr_to_string(ui_name)));
+ PUT(item, "ui_name", CSTR_TO_OBJ(ui_name));
PUT(item, "hi_name",
- STRING_OBJ(cstr_to_string(syn_id2name(e.id2))));
+ CSTR_TO_OBJ(syn_id2name(e.id2)));
break;
case kHlTerminal:
- PUT(item, "kind", STRING_OBJ(cstr_to_string("term")));
+ PUT(item, "kind", CSTR_TO_OBJ("term"));
break;
case kHlCombine:
diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c
index a0f0a947b8..09e7d04e02 100644
--- a/src/nvim/highlight_group.c
+++ b/src/nvim/highlight_group.c
@@ -697,10 +697,18 @@ int load_colors(char *name)
char *buf = xmalloc(buflen);
apply_autocmds(EVENT_COLORSCHEMEPRE, name, curbuf->b_fname, false, curbuf);
snprintf(buf, buflen, "colors/%s.vim", name);
- int retval = source_runtime(buf, DIP_START + DIP_OPT);
+ int retval = source_runtime(buf, 0);
if (retval == FAIL) {
snprintf(buf, buflen, "colors/%s.lua", name);
- retval = source_runtime(buf, DIP_START + DIP_OPT);
+ retval = source_runtime(buf, 0);
+ }
+ if (retval == FAIL) {
+ snprintf(buf, buflen, "colors/%s.vim", name);
+ retval = source_runtime(buf, DIP_NORTP + DIP_START + DIP_OPT);
+ }
+ if (retval == FAIL) {
+ snprintf(buf, buflen, "colors/%s.lua", name);
+ retval = source_runtime(buf, DIP_NORTP + DIP_START + DIP_OPT);
}
xfree(buf);
if (retval == OK) {
@@ -1420,7 +1428,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
void free_highlight(void)
{
ga_clear(&highlight_ga);
- map_destroy(cstr_t, int)(&highlight_unames);
+ map_destroy(cstr_t, &highlight_unames);
arena_mem_free(arena_finish(&highlight_arena));
}
@@ -1548,8 +1556,11 @@ static bool hlgroup2dict(Dictionary *hl, NS ns_id, int hl_id, Arena *arena)
HlAttrs attr =
syn_attr2entry(ns_id == 0 ? sgp->sg_attr : ns_get_hl(&ns_id, hl_id, false, sgp->sg_set));
*hl = arena_dict(arena, HLATTRS_DICT_SIZE + 1);
+ if (attr.rgb_ae_attr & HL_DEFAULT) {
+ PUT_C(*hl, "default", BOOLEAN_OBJ(true));
+ }
if (link > 0) {
- PUT_C(*hl, "link", STRING_OBJ(cstr_as_string(hl_table[link - 1].sg_name)));
+ PUT_C(*hl, "link", CSTR_AS_OBJ(hl_table[link - 1].sg_name));
}
Dictionary hl_cterm = arena_dict(arena, HLATTRS_DICT_SIZE);
hlattrs2dict(hl, NULL, attr, true, true);
diff --git a/src/nvim/lua/converter.h b/src/nvim/lua/converter.h
index ddc0acfbfa..241dd65cc7 100644
--- a/src/nvim/lua/converter.h
+++ b/src/nvim/lua/converter.h
@@ -6,7 +6,7 @@
#include <stdint.h>
#include "nvim/api/private/defs.h"
-#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/func_attr.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 9586b56f3c..8c1d8addcd 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -109,11 +109,16 @@ typedef enum luv_err_type {
kThreadCallback,
} luv_err_t;
+lua_State *get_global_lstate(void)
+{
+ return global_lstate;
+}
+
/// Convert lua error into a Vim error message
///
/// @param lstate Lua interpreter state.
/// @param[in] msg Message base, must contain one `%s`.
-static void nlua_error(lua_State *const lstate, const char *const msg)
+void nlua_error(lua_State *const lstate, const char *const msg)
FUNC_ATTR_NONNULL_ALL
{
size_t len;
@@ -150,7 +155,7 @@ static void nlua_error(lua_State *const lstate, const char *const msg)
/// @param lstate Lua interpreter state
/// @param[in] nargs Number of arguments expected by the function being called.
/// @param[in] nresults Number of results the function returns.
-static int nlua_pcall(lua_State *lstate, int nargs, int nresults)
+int nlua_pcall(lua_State *lstate, int nargs, int nresults)
{
lua_getglobal(lstate, "debug");
lua_getfield(lstate, -1, "traceback");
@@ -336,7 +341,7 @@ static int nlua_init_argv(lua_State *const L, char **argv, int argc, int lua_arg
lua_pushstring(L, argv[lua_arg0 - 1]);
lua_rawseti(L, -2, 0); // _G.arg[0] = "foo.lua"
- for (; lua_arg0 >= 0 && i + lua_arg0 < argc; i++) {
+ for (; i + lua_arg0 < argc; i++) {
lua_pushstring(L, argv[i + lua_arg0]);
lua_rawseti(L, -2, i + 1); // _G.arg[i+1] = "--foo"
}
@@ -836,7 +841,7 @@ void nlua_run_script(char **argv, int argc, int lua_arg0)
exit(lua_ok ? 0 : 1);
}
-lua_State *nlua_init_state(bool thread)
+static lua_State *nlua_init_state(bool thread)
{
// If it is called from the main thread, it will attempt to rebuild the cache.
const uv_thread_t self = uv_thread_self();
@@ -910,12 +915,13 @@ static void nlua_common_free_all_mem(lua_State *lstate)
if (nlua_track_refs) {
// in case there are leaked luarefs, leak the associated memory
// to get LeakSanitizer stacktraces on exit
- pmap_destroy(handle_T)(&ref_state->ref_markers);
+ map_destroy(int, &ref_state->ref_markers);
}
#endif
lua_close(lstate);
}
+
static void nlua_print_event(void **argv)
{
char *str = argv[0];
@@ -1285,7 +1291,7 @@ LuaRef nlua_ref(lua_State *lstate, nlua_ref_state_t *ref_state, int index)
#ifdef NLUA_TRACK_REFS
if (nlua_track_refs) {
// dummy allocation to make LeakSanitizer track our luarefs
- pmap_put(handle_T)(&ref_state->ref_markers, ref, xmalloc(3));
+ pmap_put(int)(&ref_state->ref_markers, ref, xmalloc(3));
}
#endif
}
@@ -1305,7 +1311,7 @@ void nlua_unref(lua_State *lstate, nlua_ref_state_t *ref_state, LuaRef ref)
#ifdef NLUA_TRACK_REFS
// NB: don't remove entry from map to track double-unref
if (nlua_track_refs) {
- xfree(pmap_get(handle_T)(&ref_state->ref_markers, ref));
+ xfree(pmap_get(int)(&ref_state->ref_markers, ref));
}
#endif
luaL_unref(lstate, LUA_REGISTRYINDEX, ref);
@@ -2275,80 +2281,3 @@ plain:
kv_printf(str, "<Lua %d>", ref);
return str.items;
}
-
-char *nlua_read_secure(const char *path)
-{
- lua_State *const lstate = global_lstate;
- const int top = lua_gettop(lstate);
-
- lua_getglobal(lstate, "vim");
- lua_getfield(lstate, -1, "secure");
- lua_getfield(lstate, -1, "read");
- lua_pushstring(lstate, path);
- if (nlua_pcall(lstate, 1, 1)) {
- nlua_error(lstate, _("Error executing vim.secure.read: %.*s"));
- lua_settop(lstate, top);
- return NULL;
- }
-
- size_t len = 0;
- const char *contents = lua_tolstring(lstate, -1, &len);
- char *buf = NULL;
- if (contents != NULL) {
- // Add one to include trailing null byte
- buf = xcalloc(len + 1, sizeof(char));
- memcpy(buf, contents, len + 1);
- }
-
- lua_settop(lstate, top);
- return buf;
-}
-
-bool nlua_trust(const char *action, const char *path)
-{
- lua_State *const lstate = global_lstate;
- const int top = lua_gettop(lstate);
-
- lua_getglobal(lstate, "vim");
- lua_getfield(lstate, -1, "secure");
- lua_getfield(lstate, -1, "trust");
-
- lua_newtable(lstate);
- lua_pushstring(lstate, "action");
- lua_pushstring(lstate, action);
- lua_settable(lstate, -3);
- if (path == NULL) {
- lua_pushstring(lstate, "bufnr");
- lua_pushnumber(lstate, 0);
- lua_settable(lstate, -3);
- } else {
- lua_pushstring(lstate, "path");
- lua_pushstring(lstate, path);
- lua_settable(lstate, -3);
- }
-
- if (nlua_pcall(lstate, 1, 2)) {
- nlua_error(lstate, _("Error executing vim.secure.trust: %.*s"));
- lua_settop(lstate, top);
- return false;
- }
-
- bool success = lua_toboolean(lstate, -2);
- const char *msg = lua_tostring(lstate, -1);
- if (msg != NULL) {
- if (success) {
- if (strcmp(action, "allow") == 0) {
- smsg("Allowed \"%s\" in trust database.", msg);
- } else if (strcmp(action, "deny") == 0) {
- smsg("Denied \"%s\" in trust database.", msg);
- } else if (strcmp(action, "remove") == 0) {
- smsg("Removed \"%s\" from trust database.", msg);
- }
- } else {
- semsg(e_trustfile, msg);
- }
- }
-
- lua_settop(lstate, top);
- return success;
-}
diff --git a/src/nvim/lua/executor.h b/src/nvim/lua/executor.h
index c6747833e5..f340d9d0d8 100644
--- a/src/nvim/lua/executor.h
+++ b/src/nvim/lua/executor.h
@@ -8,7 +8,7 @@
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/assert.h"
-#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/func_attr.h"
#include "nvim/lua/converter.h"
@@ -24,7 +24,7 @@ typedef struct {
LuaRef empty_dict_ref;
int ref_count;
#if __has_feature(address_sanitizer)
- PMap(handle_T) ref_markers;
+ PMap(int) ref_markers;
#endif
} nlua_ref_state_t;
diff --git a/src/nvim/lua/secure.c b/src/nvim/lua/secure.c
new file mode 100644
index 0000000000..30d5a95fc0
--- /dev/null
+++ b/src/nvim/lua/secure.c
@@ -0,0 +1,118 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
+#include <lauxlib.h>
+#include <lua.h>
+#include <lualib.h>
+
+#include "nvim/charset.h"
+#include "nvim/lua/executor.h"
+#include "nvim/lua/secure.h"
+#include "nvim/message.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "lua/secure.c.generated.h"
+#endif
+
+char *nlua_read_secure(const char *path)
+{
+ lua_State *const lstate = get_global_lstate();
+ const int top = lua_gettop(lstate);
+
+ lua_getglobal(lstate, "vim");
+ lua_getfield(lstate, -1, "secure");
+ lua_getfield(lstate, -1, "read");
+ lua_pushstring(lstate, path);
+ if (nlua_pcall(lstate, 1, 1)) {
+ nlua_error(lstate, _("Error executing vim.secure.read: %.*s"));
+ lua_settop(lstate, top);
+ return NULL;
+ }
+
+ size_t len = 0;
+ const char *contents = lua_tolstring(lstate, -1, &len);
+ char *buf = NULL;
+ if (contents != NULL) {
+ // Add one to include trailing null byte
+ buf = xcalloc(len + 1, sizeof(char));
+ memcpy(buf, contents, len + 1);
+ }
+
+ lua_settop(lstate, top);
+ return buf;
+}
+
+static bool nlua_trust(const char *action, const char *path)
+{
+ lua_State *const lstate = get_global_lstate();
+ const int top = lua_gettop(lstate);
+
+ lua_getglobal(lstate, "vim");
+ lua_getfield(lstate, -1, "secure");
+ lua_getfield(lstate, -1, "trust");
+
+ lua_newtable(lstate);
+ lua_pushstring(lstate, "action");
+ lua_pushstring(lstate, action);
+ lua_settable(lstate, -3);
+ if (path == NULL) {
+ lua_pushstring(lstate, "bufnr");
+ lua_pushnumber(lstate, 0);
+ lua_settable(lstate, -3);
+ } else {
+ lua_pushstring(lstate, "path");
+ lua_pushstring(lstate, path);
+ lua_settable(lstate, -3);
+ }
+
+ if (nlua_pcall(lstate, 1, 2)) {
+ nlua_error(lstate, _("Error executing vim.secure.trust: %.*s"));
+ lua_settop(lstate, top);
+ return false;
+ }
+
+ bool success = lua_toboolean(lstate, -2);
+ const char *msg = lua_tostring(lstate, -1);
+ if (msg != NULL) {
+ if (success) {
+ if (strcmp(action, "allow") == 0) {
+ smsg("Allowed \"%s\" in trust database.", msg);
+ } else if (strcmp(action, "deny") == 0) {
+ smsg("Denied \"%s\" in trust database.", msg);
+ } else if (strcmp(action, "remove") == 0) {
+ smsg("Removed \"%s\" from trust database.", msg);
+ }
+ } else {
+ semsg(e_trustfile, msg);
+ }
+ }
+
+ lua_settop(lstate, top);
+ return success;
+}
+
+void ex_trust(exarg_T *eap)
+{
+ const char *const p = skiptowhite(eap->arg);
+ char *arg1 = xmemdupz(eap->arg, (size_t)(p - eap->arg));
+ const char *action = "allow";
+ const char *path = skipwhite(p);
+
+ if (strcmp(arg1, "++deny") == 0) {
+ action = "deny";
+ } else if (strcmp(arg1, "++remove") == 0) {
+ action = "remove";
+ } else if (*arg1 != '\0') {
+ semsg(e_invarg2, arg1);
+ goto theend;
+ }
+
+ if (path[0] == '\0') {
+ path = NULL;
+ }
+
+ nlua_trust(action, path);
+
+theend:
+ xfree(arg1);
+}
diff --git a/src/nvim/lua/secure.h b/src/nvim/lua/secure.h
new file mode 100644
index 0000000000..87c468538e
--- /dev/null
+++ b/src/nvim/lua/secure.h
@@ -0,0 +1,12 @@
+#ifndef NVIM_LUA_SECURE_H
+#define NVIM_LUA_SECURE_H
+
+#include <lua.h>
+
+#include "nvim/ex_cmds_defs.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "lua/secure.h.generated.h"
+#endif
+
+#endif // NVIM_LUA_SECURE_H
diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c
index da64685a40..a9e7838980 100644
--- a/src/nvim/lua/treesitter.c
+++ b/src/nvim/lua/treesitter.c
@@ -20,6 +20,7 @@
#include "nvim/api/private/helpers.h"
#include "nvim/buffer_defs.h"
#include "nvim/globals.h"
+#include "nvim/lua/executor.h"
#include "nvim/lua/treesitter.h"
#include "nvim/macros.h"
#include "nvim/map.h"
@@ -43,6 +44,13 @@ typedef struct {
int max_match_id;
} TSLua_cursor;
+typedef struct {
+ LuaRef cb;
+ lua_State *lstate;
+ bool lex;
+ bool parse;
+} TSLuaLoggerOpts;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "lua/treesitter.c.generated.h"
#endif
@@ -56,6 +64,8 @@ static struct luaL_Reg parser_meta[] = {
{ "included_ranges", parser_get_ranges },
{ "set_timeout", parser_set_timeout },
{ "timeout", parser_get_timeout },
+ { "_set_logger", parser_set_logger },
+ { "_logger", parser_get_logger },
{ NULL, NULL }
};
@@ -231,9 +241,9 @@ int tslua_remove_lang(lua_State *L)
const char *lang_name = luaL_checkstring(L, 1);
bool present = pmap_has(cstr_t)(&langs, lang_name);
if (present) {
- char *key = (char *)pmap_key(cstr_t)(&langs, lang_name);
- pmap_del(cstr_t)(&langs, lang_name);
- xfree(key);
+ cstr_t key;
+ pmap_del(cstr_t)(&langs, lang_name, &key);
+ xfree((void *)key);
}
lua_pushboolean(L, present);
return 1;
@@ -322,6 +332,12 @@ static int parser_gc(lua_State *L)
return 0;
}
+ TSLogger logger = ts_parser_logger(*p);
+ if (logger.log) {
+ TSLuaLoggerOpts *opts = (TSLuaLoggerOpts *)logger.payload;
+ xfree(opts);
+ }
+
ts_parser_delete(*p);
return 0;
}
@@ -669,9 +685,82 @@ static int parser_get_timeout(lua_State *L)
}
lua_pushinteger(L, (long)ts_parser_timeout_micros(*p));
+ return 1;
+}
+
+static void logger_cb(void *payload, TSLogType logtype, const char *s)
+{
+ TSLuaLoggerOpts *opts = (TSLuaLoggerOpts *)payload;
+ if ((!opts->lex && logtype == TSLogTypeLex)
+ || (!opts->parse && logtype == TSLogTypeParse)) {
+ return;
+ }
+
+ lua_State *lstate = opts->lstate;
+
+ nlua_pushref(lstate, opts->cb);
+ lua_pushstring(lstate, logtype == TSLogTypeParse ? "parse" : "lex");
+ lua_pushstring(lstate, s);
+ if (lua_pcall(lstate, 2, 0, 0)) {
+ luaL_error(lstate, "Error executing treesitter logger callback");
+ }
+}
+
+static int parser_set_logger(lua_State *L)
+{
+ TSParser **p = parser_check(L, 1);
+ if (!p) {
+ return 0;
+ }
+
+ if (!lua_isboolean(L, 2)) {
+ return luaL_argerror(L, 2, "boolean expected");
+ }
+
+ if (!lua_isboolean(L, 3)) {
+ return luaL_argerror(L, 3, "boolean expected");
+ }
+
+ if (!lua_isfunction(L, 4)) {
+ return luaL_argerror(L, 4, "function expected");
+ }
+
+ TSLuaLoggerOpts *opts = xmalloc(sizeof(TSLuaLoggerOpts));
+
+ *opts = (TSLuaLoggerOpts){
+ .lex = lua_toboolean(L, 2),
+ .parse = lua_toboolean(L, 3),
+ .cb = nlua_ref_global(L, 4),
+ .lstate = L
+ };
+
+ TSLogger logger = {
+ .payload = (void *)opts,
+ .log = logger_cb
+ };
+
+ ts_parser_set_logger(*p, logger);
return 0;
}
+static int parser_get_logger(lua_State *L)
+{
+ TSParser **p = parser_check(L, 1);
+ if (!p) {
+ return 0;
+ }
+
+ TSLogger logger = ts_parser_logger(*p);
+ if (logger.log) {
+ TSLuaLoggerOpts *opts = (TSLuaLoggerOpts *)logger.payload;
+ nlua_pushref(L, opts->cb);
+ } else {
+ lua_pushnil(L);
+ }
+
+ return 1;
+}
+
// Tree methods
/// push tree interface on lua stack.
@@ -1349,6 +1438,11 @@ static int node_rawquery(lua_State *L)
} else {
cursor = ts_query_cursor_new();
}
+
+#ifdef NVIM_TS_HAS_SET_MAX_START_DEPTH
+ // reset the start depth
+ ts_query_cursor_set_max_start_depth(cursor, 0);
+#endif
ts_query_cursor_set_match_limit(cursor, 256);
ts_query_cursor_exec(cursor, query, node);
@@ -1360,6 +1454,29 @@ static int node_rawquery(lua_State *L)
ts_query_cursor_set_point_range(cursor, (TSPoint){ start, 0 }, (TSPoint){ end, 0 });
}
+ if (lua_gettop(L) >= 6 && !lua_isnil(L, 6)) {
+ if (!lua_istable(L, 6)) {
+ return luaL_error(L, "table expected");
+ }
+ lua_pushnil(L);
+ // stack: [dict, ..., nil]
+ while (lua_next(L, 6)) {
+ // stack: [dict, ..., key, value]
+ if (lua_type(L, -2) == LUA_TSTRING) {
+ char *k = (char *)lua_tostring(L, -2);
+ if (strequal("max_start_depth", k)) {
+ // TODO(lewis6991): remove ifdef when min TS version is 0.20.9
+#ifdef NVIM_TS_HAS_SET_MAX_START_DEPTH
+ uint32_t max_start_depth = (uint32_t)lua_tointeger(L, -1);
+ ts_query_cursor_set_max_start_depth(cursor, max_start_depth);
+#endif
+ }
+ }
+ lua_pop(L, 1); // pop the value; lua_next will pop the key.
+ // stack: [dict, ..., key]
+ }
+ }
+
TSLua_cursor *ud = lua_newuserdata(L, sizeof(*ud)); // [udata]
ud->cursor = cursor;
ud->predicated_match = -1;
diff --git a/src/nvim/main.c b/src/nvim/main.c
index ee643adab5..d4fbf8ce93 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -49,6 +49,7 @@
#include "nvim/keycodes.h"
#include "nvim/log.h"
#include "nvim/lua/executor.h"
+#include "nvim/lua/secure.h"
#include "nvim/macros.h"
#include "nvim/main.h"
#include "nvim/mark.h"
@@ -443,8 +444,7 @@ int main(int argc, char **argv)
// If using the runtime (-u is not NONE), enable syntax & filetype plugins.
if (!vimrc_none || params.clean) {
- // Sources filetype.lua and filetype.vim unless the user explicitly disabled it with :filetype
- // off.
+ // Sources filetype.lua unless the user explicitly disabled it with :filetype off.
filetype_maybe_enable();
// Sources syntax/syntax.vim. We do this *after* the user startup scripts so that users can
// disable syntax highlighting with `:syntax off` if they wish.
@@ -2227,3 +2227,17 @@ static void check_swap_exists_action(void)
}
handle_swap_exists(NULL);
}
+
+#ifdef ENABLE_ASAN_UBSAN
+const char *__ubsan_default_options(void);
+const char *__ubsan_default_options(void)
+{
+ return "print_stacktrace=1";
+}
+
+const char *__asan_default_options(void);
+const char *__asan_default_options(void)
+{
+ return "handle_abort=1,handle_sigill=1";
+}
+#endif
diff --git a/src/nvim/map.c b/src/nvim/map.c
index 191a459863..4c8506f468 100644
--- a/src/nvim/map.c
+++ b/src/nvim/map.c
@@ -16,7 +16,6 @@
#include "klib/khash.h"
#include "nvim/gettext.h"
#include "nvim/map.h"
-#include "nvim/map_defs.h"
#include "nvim/memory.h"
#define cstr_t_hash kh_str_hash_func
@@ -29,8 +28,6 @@
#define int_eq kh_int_hash_equal
#define handle_T_hash kh_int_hash_func
#define handle_T_eq kh_int_hash_equal
-#define KittyKey_hash kh_int_hash_func
-#define KittyKey_eq kh_int_hash_equal
#if defined(ARCH_64)
# define ptr_t_hash(key) uint64_t_hash((uint64_t)(key))
@@ -45,74 +42,69 @@
#define DEFAULT_INITIALIZER { 0 }
#define SSIZE_INITIALIZER { -1 }
+#define KEY_IMPL(T) \
+ __KHASH_IMPL(T, , T, T##_hash, T##_eq) \
+
#define MAP_IMPL(T, U, ...) \
INITIALIZER_DECLARE(T, U, __VA_ARGS__); \
- __KHASH_IMPL(T##_##U##_map, , T, U, 1, T##_hash, T##_eq) \
- void map_##T##_##U##_destroy(Map(T, U) *map) \
- { \
- kh_dealloc(T##_##U##_map, &map->table); \
- } \
U map_##T##_##U##_get(Map(T, U) *map, T key) \
{ \
khiter_t k; \
- if ((k = kh_get(T##_##U##_map, &map->table, key)) == kh_end(&map->table)) { \
+ if ((k = kh_get(T, &map->table, key)) == kh_end(&map->table)) { \
return INITIALIZER(T, U); \
} \
- return kh_val(&map->table, k); \
- } \
- bool map_##T##_##U##_has(Map(T, U) *map, T key) \
- { \
- return kh_get(T##_##U##_map, &map->table, key) != kh_end(&map->table); \
- } \
- T map_##T##_##U##_key(Map(T, U) *map, T key) \
- { \
- khiter_t k; \
- if ((k = kh_get(T##_##U##_map, &map->table, key)) == kh_end(&map->table)) { \
- abort(); /* Caller must check map_has(). */ \
- } \
- return kh_key(&map->table, k); \
+ return kh_val(U, &map->table, k); \
} \
U map_##T##_##U##_put(Map(T, U) *map, T key, U value) \
{ \
+ STATIC_ASSERT(sizeof(U) <= KHASH_MAX_VAL_SIZE, "increase KHASH_MAX_VAL_SIZE"); \
int ret; \
U rv = INITIALIZER(T, U); \
- khiter_t k = kh_put(T##_##U##_map, &map->table, key, &ret); \
+ khiter_t k = kh_put(T, &map->table, key, &ret, sizeof(U)); \
if (!ret) { \
- rv = kh_val(&map->table, k); \
+ rv = kh_val(U, &map->table, k); \
} \
- kh_val(&map->table, k) = value; \
+ kh_val(U, &map->table, k) = value; \
return rv; \
} \
- U *map_##T##_##U##_ref(Map(T, U) *map, T key, bool put) \
+ U *map_##T##_##U##_ref(Map(T, U) *map, T key, T **key_alloc) \
+ { \
+ khiter_t k = kh_get(T, &map->table, key); \
+ if (k == kh_end(&map->table)) { \
+ return NULL; \
+ } \
+ if (key_alloc) { \
+ *key_alloc = &kh_key(&map->table, k); \
+ } \
+ return &kh_val(U, &map->table, k); \
+ } \
+ U *map_##T##_##U##_put_ref(Map(T, U) *map, T key, T **key_alloc, bool *new_item) \
{ \
int ret; \
- khiter_t k; \
- if (put) { \
- k = kh_put(T##_##U##_map, &map->table, key, &ret); \
- if (ret) { \
- kh_val(&map->table, k) = INITIALIZER(T, U); \
- } \
- } else { \
- k = kh_get(T##_##U##_map, &map->table, key); \
- if (k == kh_end(&map->table)) { \
- return NULL; \
- } \
+ khiter_t k = kh_put(T, &map->table, key, &ret, sizeof(U)); \
+ if (ret) { \
+ kh_val(U, &map->table, k) = INITIALIZER(T, U); \
} \
- return &kh_val(&map->table, k); \
+ if (new_item) { \
+ *new_item = (bool)ret; \
+ } \
+ if (key_alloc) { \
+ *key_alloc = &kh_key(&map->table, k); \
+ } \
+ return &kh_val(U, &map->table, k); \
} \
- U map_##T##_##U##_del(Map(T, U) *map, T key) \
+ U map_##T##_##U##_del(Map(T, U) *map, T key, T *key_alloc) \
{ \
U rv = INITIALIZER(T, U); \
khiter_t k; \
- if ((k = kh_get(T##_##U##_map, &map->table, key)) != kh_end(&map->table)) { \
- rv = kh_val(&map->table, k); \
- kh_del(T##_##U##_map, &map->table, k); \
+ if ((k = kh_get(T, &map->table, key)) != kh_end(&map->table)) { \
+ rv = kh_val(U, &map->table, k); \
+ if (key_alloc) { \
+ *key_alloc = kh_key(&map->table, k); \
+ } \
+ kh_del(T, &map->table, k); \
} \
return rv; \
- } \
- void map_##T##_##U##_clear(Map(T, U) *map) \
- { \
- kh_clear(T##_##U##_map, &map->table); \
}
static inline khint_t String_hash(String s)
@@ -162,7 +154,17 @@ static inline bool ColorKey_eq(ColorKey ae1, ColorKey ae2)
return memcmp(&ae1, &ae2, sizeof(ae1)) == 0;
}
+KEY_IMPL(int)
+KEY_IMPL(cstr_t)
+KEY_IMPL(ptr_t)
+KEY_IMPL(uint64_t)
+KEY_IMPL(uint32_t)
+KEY_IMPL(String)
+KEY_IMPL(HlEntry)
+KEY_IMPL(ColorKey)
+
MAP_IMPL(int, int, DEFAULT_INITIALIZER)
+MAP_IMPL(int, ptr_t, DEFAULT_INITIALIZER)
MAP_IMPL(int, cstr_t, DEFAULT_INITIALIZER)
MAP_IMPL(cstr_t, ptr_t, DEFAULT_INITIALIZER)
MAP_IMPL(cstr_t, int, DEFAULT_INITIALIZER)
@@ -172,26 +174,19 @@ MAP_IMPL(uint64_t, ptr_t, DEFAULT_INITIALIZER)
MAP_IMPL(uint64_t, ssize_t, SSIZE_INITIALIZER)
MAP_IMPL(uint64_t, uint64_t, DEFAULT_INITIALIZER)
MAP_IMPL(uint32_t, uint32_t, DEFAULT_INITIALIZER)
-MAP_IMPL(handle_T, ptr_t, DEFAULT_INITIALIZER)
MAP_IMPL(HlEntry, int, DEFAULT_INITIALIZER)
MAP_IMPL(String, handle_T, 0)
MAP_IMPL(String, int, DEFAULT_INITIALIZER)
MAP_IMPL(int, String, DEFAULT_INITIALIZER)
-
MAP_IMPL(ColorKey, ColorItem, COLOR_ITEM_INITIALIZER)
-MAP_IMPL(KittyKey, cstr_t, DEFAULT_INITIALIZER)
-
/// Deletes a key:value pair from a string:pointer map, and frees the
/// storage of both key and value.
///
void pmap_del2(PMap(cstr_t) *map, const char *key)
{
- if (pmap_has(cstr_t)(map, key)) {
- void *k = (void *)pmap_key(cstr_t)(map, key);
- void *v = pmap_get(cstr_t)(map, key);
- pmap_del(cstr_t)(map, key);
- xfree(k);
- xfree(v);
- }
+ cstr_t key_alloc = NULL;
+ ptr_t val = pmap_del(cstr_t)(map, key, &key_alloc);
+ xfree((void *)key_alloc);
+ xfree(val);
}
diff --git a/src/nvim/map.h b/src/nvim/map.h
index 92f0b32255..cc32a20740 100644
--- a/src/nvim/map.h
+++ b/src/nvim/map.h
@@ -7,39 +7,71 @@
#include "klib/khash.h"
#include "nvim/api/private/defs.h"
-#include "nvim/extmark_defs.h"
-#include "nvim/gettext.h"
+#include "nvim/assert.h"
#include "nvim/highlight_defs.h"
-#include "nvim/map_defs.h"
-#include "nvim/tui/input_defs.h"
#include "nvim/types.h"
-#include "nvim/ui_client.h"
#if defined(__NetBSD__)
# undef uint64_t
# define uint64_t uint64_t
#endif
+typedef const char *cstr_t;
+typedef void *ptr_t;
+
+#define Map(T, U) Map_##T##_##U
+#define PMap(T) Map(T, ptr_t)
+
+#define KEY_DECLS(T) \
+ KHASH_DECLARE(T) \
+ static inline bool set_put_##T(Set(T) *set, T key, T **key_alloc) { \
+ int kh_ret; \
+ khiter_t k = kh_put(T, set, key, &kh_ret, 0); \
+ if (key_alloc) { \
+ *key_alloc = &kh_key(set, k); \
+ } \
+ return kh_ret; \
+ } \
+ static inline void set_del_##T(Set(T) *set, T key) \
+ { \
+ khiter_t k; \
+ if ((k = kh_get(T, set, key)) != kh_end(set)) { \
+ kh_del(T, set, k); \
+ } \
+ } \
+ static inline bool set_has_##T(Set(T) *set, T key) { \
+ return (kh_get(T, set, key) != kh_end(set)); \
+ } \
+
#define MAP_DECLS(T, U) \
- KHASH_DECLARE(T##_##U##_map, T, U) \
typedef struct { \
- khash_t(T##_##U##_map) table; \
+ khash_t(T) table; \
} Map(T, U); \
- Map(T, U) *map_##T##_##U##_new(void); \
- void map_##T##_##U##_free(Map(T, U) *map); \
- void map_##T##_##U##_destroy(Map(T, U) *map); \
U map_##T##_##U##_get(Map(T, U) *map, T key); \
- bool map_##T##_##U##_has(Map(T, U) *map, T key); \
- T map_##T##_##U##_key(Map(T, U) *map, T key); \
+ static inline bool map_##T##_##U##_has(Map(T, U) *map, T key) \
+ { \
+ return kh_get(T, &map->table, key) != kh_end(&map->table); \
+ } \
U map_##T##_##U##_put(Map(T, U) *map, T key, U value); \
- U *map_##T##_##U##_ref(Map(T, U) *map, T key, bool put); \
- U map_##T##_##U##_del(Map(T, U) *map, T key); \
- void map_##T##_##U##_clear(Map(T, U) *map);
+ U *map_##T##_##U##_ref(Map(T, U) *map, T key, T **key_alloc); \
+ U *map_##T##_##U##_put_ref(Map(T, U) *map, T key, T **key_alloc, bool *new_item); \
+ U map_##T##_##U##_del(Map(T, U) *map, T key, T *key_alloc); \
-//
// NOTE: Keys AND values must be allocated! khash.h does not make a copy.
-//
+
+#define Set(type) khash_t(type)
+
+KEY_DECLS(int)
+KEY_DECLS(cstr_t)
+KEY_DECLS(ptr_t)
+KEY_DECLS(uint64_t)
+KEY_DECLS(uint32_t)
+KEY_DECLS(String)
+KEY_DECLS(HlEntry)
+KEY_DECLS(ColorKey)
+
MAP_DECLS(int, int)
+MAP_DECLS(int, ptr_t)
MAP_DECLS(int, cstr_t)
MAP_DECLS(cstr_t, ptr_t)
MAP_DECLS(cstr_t, int)
@@ -49,48 +81,50 @@ MAP_DECLS(uint64_t, ptr_t)
MAP_DECLS(uint64_t, ssize_t)
MAP_DECLS(uint64_t, uint64_t)
MAP_DECLS(uint32_t, uint32_t)
-
-MAP_DECLS(handle_T, ptr_t)
MAP_DECLS(HlEntry, int)
MAP_DECLS(String, handle_T)
MAP_DECLS(String, int)
MAP_DECLS(int, String)
-
MAP_DECLS(ColorKey, ColorItem)
-MAP_DECLS(KittyKey, cstr_t)
-
-#define MAP_INIT { { 0, 0, 0, 0, NULL, NULL, NULL } }
-#define map_init(k, v, map) do { *(map) = (Map(k, v)) MAP_INIT; } while (false)
+#define SET_INIT { 0, 0, 0, 0, NULL, NULL, NULL }
+#define MAP_INIT { SET_INIT }
-#define map_destroy(T, U) map_##T##_##U##_destroy
#define map_get(T, U) map_##T##_##U##_get
#define map_has(T, U) map_##T##_##U##_has
-#define map_key(T, U) map_##T##_##U##_key
#define map_put(T, U) map_##T##_##U##_put
#define map_ref(T, U) map_##T##_##U##_ref
+#define map_put_ref(T, U) map_##T##_##U##_put_ref
#define map_del(T, U) map_##T##_##U##_del
-#define map_clear(T, U) map_##T##_##U##_clear
+#define map_destroy(T, map) kh_dealloc(T, &(map)->table)
+#define map_clear(T, map) kh_clear(T, &(map)->table)
#define map_size(map) ((map)->table.size)
-#define pmap_destroy(T) map_destroy(T, ptr_t)
#define pmap_get(T) map_get(T, ptr_t)
#define pmap_has(T) map_has(T, ptr_t)
-#define pmap_key(T) map_key(T, ptr_t)
#define pmap_put(T) map_put(T, ptr_t)
#define pmap_ref(T) map_ref(T, ptr_t)
+#define pmap_put_ref(T) map_put_ref(T, ptr_t)
/// @see pmap_del2
#define pmap_del(T) map_del(T, ptr_t)
-#define pmap_clear(T) map_clear(T, ptr_t)
-#define pmap_init(k, map) map_init(k, ptr_t, map)
-#define map_foreach(map, key, value, block) \
- kh_foreach(&(map)->table, key, value, block)
+#define map_foreach(U, map, key, value, block) kh_foreach(U, &(map)->table, key, value, block)
-#define map_foreach_value(map, value, block) \
- kh_foreach_value(&(map)->table, value, block)
+#define map_foreach_value(U, map, value, block) kh_foreach_value(U, &(map)->table, value, block)
+#define map_foreach_key(map, key, block) kh_foreach_key(&(map)->table, key, block)
+#define set_foreach(set, key, block) kh_foreach_key(set, key, block)
+
+#define pmap_foreach_value(map, value, block) map_foreach_value(ptr_t, map, value, block)
+#define pmap_foreach(map, key, value, block) map_foreach(ptr_t, map, key, value, block)
void pmap_del2(PMap(cstr_t) *map, const char *key);
+#define set_has(T, set, key) set_has_##T(set, key)
+#define set_put(T, set, key) set_put_##T(set, key, NULL)
+#define set_put_ref(T, set, key, key_alloc) set_put_##T(set, key, key_alloc)
+#define set_del(T, set, key) set_del_##T(set, key)
+#define set_destroy(T, set) kh_dealloc(T, set)
+#define set_clear(T, set) kh_clear(T, set)
+
#endif // NVIM_MAP_H
diff --git a/src/nvim/map_defs.h b/src/nvim/map_defs.h
deleted file mode 100644
index 61afedbe50..0000000000
--- a/src/nvim/map_defs.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef NVIM_MAP_DEFS_H
-#define NVIM_MAP_DEFS_H
-
-#include "klib/khash.h"
-
-typedef const char *cstr_t;
-typedef void *ptr_t;
-
-#define Map(T, U) Map_##T##_##U
-#define PMap(T) Map(T, ptr_t)
-
-#endif // NVIM_MAP_DEFS_H
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c
index c5449bd66e..e40e67cead 100644
--- a/src/nvim/mapping.c
+++ b/src/nvim/mapping.c
@@ -2096,13 +2096,13 @@ static Dictionary mapblock_fill_dict(const mapblock_T *const mp, const char *lhs
: cstr_as_string(str2special_save(mp->m_str, false, true))));
}
if (mp->m_desc != NULL) {
- PUT(dict, "desc", STRING_OBJ(cstr_to_string(mp->m_desc)));
+ PUT(dict, "desc", CSTR_TO_OBJ(mp->m_desc));
}
- PUT(dict, "lhs", STRING_OBJ(cstr_as_string(lhs)));
- PUT(dict, "lhsraw", STRING_OBJ(cstr_to_string(mp->m_keys)));
+ PUT(dict, "lhs", CSTR_AS_OBJ(lhs));
+ PUT(dict, "lhsraw", CSTR_TO_OBJ(mp->m_keys));
if (lhsrawalt != NULL) {
// Also add the value for the simplified entry.
- PUT(dict, "lhsrawalt", STRING_OBJ(cstr_to_string(lhsrawalt)));
+ PUT(dict, "lhsrawalt", CSTR_TO_OBJ(lhsrawalt));
}
PUT(dict, "noremap", INTEGER_OBJ(noremap_value));
PUT(dict, "script", INTEGER_OBJ(mp->m_noremap == REMAP_SCRIPT ? 1 : 0));
@@ -2115,7 +2115,7 @@ static Dictionary mapblock_fill_dict(const mapblock_T *const mp, const char *lhs
if (mp->m_replace_keycodes) {
PUT(dict, "replace_keycodes", INTEGER_OBJ(1));
}
- PUT(dict, "mode", STRING_OBJ(cstr_as_string(mapmode)));
+ PUT(dict, "mode", CSTR_AS_OBJ(mapmode));
return dict;
}
diff --git a/src/nvim/mark_defs.h b/src/nvim/mark_defs.h
index f9df0028db..cfe19eac6f 100644
--- a/src/nvim/mark_defs.h
+++ b/src/nvim/mark_defs.h
@@ -1,7 +1,7 @@
#ifndef NVIM_MARK_DEFS_H
#define NVIM_MARK_DEFS_H
-#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/os/time.h"
#include "nvim/pos.h"
diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c
index 757906d42f..840b6b646e 100644
--- a/src/nvim/marktree.c
+++ b/src/nvim/marktree.c
@@ -359,7 +359,7 @@ uint64_t marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
}
b->n_keys--;
- pmap_del(uint64_t)(b->id2node, id);
+ pmap_del(uint64_t)(b->id2node, id, NULL);
// 5.
bool itr_dirty = false;
@@ -549,8 +549,8 @@ void marktree_clear(MarkTree *b)
b->root = NULL;
}
if (b->id2node->table.keys) {
- pmap_destroy(uint64_t)(b->id2node);
- pmap_init(uint64_t, b->id2node);
+ map_destroy(uint64_t, b->id2node);
+ *b->id2node = (PMap(uint64_t)) MAP_INIT;
}
b->n_keys = 0;
b->n_nodes = 0;
diff --git a/src/nvim/marktree.h b/src/nvim/marktree.h
index 29d2abcd46..cd56115b58 100644
--- a/src/nvim/marktree.h
+++ b/src/nvim/marktree.h
@@ -9,7 +9,6 @@
#include "nvim/assert.h"
#include "nvim/garray.h"
#include "nvim/map.h"
-#include "nvim/map_defs.h"
#include "nvim/pos.h"
#include "nvim/types.h"
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index 7d61b918d2..66c26275f1 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -2024,6 +2024,24 @@ int mb_charlen(const char *str)
return count;
}
+int mb_charlen2bytelen(const char *str, int charlen)
+{
+ const char *p = str;
+ int count = 0;
+
+ if (p == NULL) {
+ return 0;
+ }
+
+ for (int i = 0; *p != NUL && i < charlen; i++) {
+ int b = utfc_ptr2len(p);
+ p += b;
+ count += b;
+ }
+
+ return count;
+}
+
/// Like mb_charlen() but for a string with specified length.
int mb_charlen_len(const char *str, int len)
{
diff --git a/src/nvim/mbyte.h b/src/nvim/mbyte.h
index 780f33e05b..724a16014d 100644
--- a/src/nvim/mbyte.h
+++ b/src/nvim/mbyte.h
@@ -5,7 +5,7 @@
#include <stdint.h>
#include <string.h>
-#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/func_attr.h"
#include "nvim/mbyte_defs.h"
#include "nvim/os/os_defs.h"
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index b9a26e1ac6..1f550ffb01 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -664,6 +664,7 @@ char *arena_memdupz(Arena *arena, const char *buf, size_t size)
# include "nvim/getchar.h"
# include "nvim/grid.h"
# include "nvim/mark.h"
+# include "nvim/msgpack_rpc/channel.h"
# include "nvim/ops.h"
# include "nvim/option.h"
# include "nvim/os/os.h"
@@ -823,6 +824,7 @@ void free_all_mem(void)
ui_free_all_mem();
nlua_free_all_mem();
+ rpc_free_all_mem();
// should be last, in case earlier free functions deallocates arenas
arena_free_reuse_blks();
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index 16fea2ccf1..898e3ddd27 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -559,7 +559,7 @@ static int remove_menu(vimmenu_T **menup, char *name, int modes, bool silent)
}
} else if (*name != NUL) {
if (!silent) {
- emsg(_(e_menuothermode));
+ emsg(_(e_menu_only_exists_in_another_mode));
}
return FAIL;
}
@@ -760,7 +760,7 @@ static vimmenu_T *find_menu(vimmenu_T *menu, char *name, int modes)
emsg(_(e_notsubmenu));
return NULL;
} else if ((menu->modes & modes) == 0x0) {
- emsg(_(e_menuothermode));
+ emsg(_(e_menu_only_exists_in_another_mode));
return NULL;
} else if (*p == NUL) { // found a full match
return menu;
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 63bcf3e069..1cb4a3cbf4 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -181,7 +181,7 @@ void msg_grid_validate(void)
msg_grid.dirty_col = xcalloc((size_t)Rows, sizeof(*msg_grid.dirty_col));
// Tricky: allow resize while pager or ex mode is active
- int pos = MAX(max_rows - msg_scrolled, 0);
+ int pos = (State & MODE_ASKMORE) ? 0 : MAX(max_rows - msg_scrolled, 0);
msg_grid.throttled = false; // don't throttle in 'cmdheight' area
msg_grid_set_pos(pos, msg_scrolled);
ui_comp_put_grid(&msg_grid, pos, 0, msg_grid.rows, msg_grid.cols,
@@ -1069,7 +1069,7 @@ void ex_messages(void *const eap_p)
for (; p != NULL; p = p->next) {
if (kv_size(p->multiattr) || (p->msg && p->msg[0])) {
Array entry = ARRAY_DICT_INIT;
- ADD(entry, STRING_OBJ(cstr_to_string(p->kind)));
+ ADD(entry, CSTR_TO_OBJ(p->kind));
Array content = ARRAY_DICT_INIT;
if (kv_size(p->multiattr)) {
for (uint32_t i = 0; i < kv_size(p->multiattr); i++) {
@@ -1082,7 +1082,7 @@ void ex_messages(void *const eap_p)
} else if (p->msg && p->msg[0]) {
Array content_entry = ARRAY_DICT_INIT;
ADD(content_entry, INTEGER_OBJ(p->attr));
- ADD(content_entry, STRING_OBJ(cstr_to_string(p->msg)));
+ ADD(content_entry, CSTR_TO_OBJ(p->msg));
ADD(content, ARRAY_OBJ(content_entry));
}
ADD(entry, ARRAY_OBJ(content));
diff --git a/src/nvim/move.c b/src/nvim/move.c
index e09a95af70..9e8abbcd96 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -164,19 +164,25 @@ static void redraw_for_cursorcolumn(win_T *wp)
}
}
-/// Calculates how much overlap the smoothscroll marker "<<<" overlaps with
-/// buffer text for curwin.
+/// Calculates how much the 'listchars' "precedes" or 'smoothscroll' "<<<"
+/// marker overlaps with buffer text for window "wp".
/// Parameter "extra2" should be the padding on the 2nd line, not the first
/// line.
/// Returns the number of columns of overlap with buffer text, excluding the
/// extra padding on the ledge.
-static int smoothscroll_marker_overlap(win_T *wp, int extra2)
+int sms_marker_overlap(win_T *wp, int extra2)
{
- // We don't draw the <<< marker when in showbreak mode, thus no need to
+ // There is no marker overlap when in showbreak mode, thus no need to
// account for it. See grid_put_linebuf().
if (*get_showbreak_value(wp) != NUL) {
return 0;
}
+
+ // Overlap when 'list' and 'listchars' "precedes" are set is 1.
+ if (wp->w_p_list && wp->w_p_lcs_chars.prec) {
+ return 1;
+ }
+
return extra2 > 3 ? 0 : 3 - extra2;
}
@@ -212,8 +218,6 @@ static void reset_skipcol(win_T *wp)
// Update curwin->w_topline to move the cursor onto the screen.
void update_topline(win_T *wp)
{
- linenr_T old_topline;
- int old_topfill;
bool check_botline = false;
long *so_ptr = wp->w_p_so >= 0 ? &wp->w_p_so : &p_so;
long save_so = *so_ptr;
@@ -243,8 +247,8 @@ void update_topline(win_T *wp)
*so_ptr = mouse_dragging - 1;
}
- old_topline = wp->w_topline;
- old_topfill = wp->w_topfill;
+ linenr_T old_topline = wp->w_topline;
+ int old_topfill = wp->w_topfill;
// If the buffer is empty, always set topline to 1.
if (buf_is_empty(curbuf)) { // special case - file is empty
@@ -271,12 +275,11 @@ void update_topline(win_T *wp)
} else if (wp->w_skipcol > 0 && wp->w_cursor.lnum == wp->w_topline) {
colnr_T vcol;
- // Check that the cursor position is visible. Add columns for the
- // smoothscroll marker "<<<" displayed in the top-left if needed.
+ // Check that the cursor position is visible. Add columns for
+ // the marker displayed in the top-left if needed.
getvvcol(wp, &wp->w_cursor, &vcol, NULL, NULL);
- int smoothscroll_overlap = smoothscroll_marker_overlap(wp,
- win_col_off(wp) - win_col_off2(wp));
- if (wp->w_skipcol + smoothscroll_overlap > vcol) {
+ int overlap = sms_marker_overlap(wp, win_col_off(wp) - win_col_off2(wp));
+ if (wp->w_skipcol + overlap > vcol) {
check_topline = true;
}
}
@@ -408,7 +411,13 @@ void update_topline(win_T *wp)
|| wp->w_topfill != old_topfill) {
dollar_vcol = -1;
redraw_later(wp, UPD_VALID);
- reset_skipcol(wp);
+
+ // When 'smoothscroll' is not set, should reset w_skipcol.
+ if (!wp->w_p_sms) {
+ reset_skipcol(wp);
+ } else if (wp->w_skipcol != 0) {
+ redraw_later(wp, UPD_SOME_VALID);
+ }
// May need to set w_skipcol when cursor in w_topline.
if (wp->w_cursor.lnum == wp->w_topline) {
@@ -652,7 +661,7 @@ static void curs_rows(win_T *wp)
i--; // hold at inserted lines
}
}
- if (valid && (lnum != wp->w_topline || !win_may_fill(wp))) {
+ if (valid && (lnum != wp->w_topline || (wp->w_skipcol == 0 && !win_may_fill(wp)))) {
lnum = wp->w_lines[i].wl_lastlnum + 1;
// Cursor inside folded lines, don't count this row
if (lnum > wp->w_cursor.lnum) {
@@ -1315,14 +1324,6 @@ bool scrolldown(long line_count, int byfold)
return moved;
}
-/// Return TRUE if scrollup() will scroll by screen line rather than text line.
-static int scrolling_screenlines(bool byfold)
-{
- return (curwin->w_p_wrap && curwin->w_p_sms)
- || (byfold && hasAnyFolding(curwin))
- || (curwin->w_p_diff && !curwin->w_p_wrap);
-}
-
/// Scroll the current window up by "line_count" logical lines. "CTRL-E"
///
/// @param line_count number of lines to scroll
@@ -1333,7 +1334,7 @@ bool scrollup(long line_count, int byfold)
linenr_T botline = curwin->w_botline;
int do_sms = curwin->w_p_wrap && curwin->w_p_sms;
- if (scrolling_screenlines(byfold) || win_may_fill(curwin)) {
+ if (do_sms || (byfold && hasAnyFolding(curwin)) || win_may_fill(curwin)) {
int width1 = curwin->w_width_inner - curwin_col_off();
int width2 = width1 + curwin_col_off2();
unsigned size = 0;
@@ -1431,10 +1432,9 @@ bool scrollup(long line_count, int byfold)
long scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
int space_cols = (curwin->w_height_inner - 1) * width2;
- // If we have non-zero scrolloff, just ignore the <<< marker as we are
+ // If we have non-zero scrolloff, just ignore the marker as we are
// going past it anyway.
- int smoothscroll_overlap = scrolloff_cols != 0 ? 0 :
- smoothscroll_marker_overlap(curwin, extra2);
+ int overlap = scrolloff_cols != 0 ? 0 : sms_marker_overlap(curwin, extra2);
// Make sure the cursor is in a visible part of the line, taking
// 'scrolloff' into account, but using screen lines.
@@ -1443,13 +1443,13 @@ bool scrollup(long line_count, int byfold)
scrolloff_cols = space_cols / 2;
}
validate_virtcol();
- if (curwin->w_virtcol < curwin->w_skipcol + smoothscroll_overlap + scrolloff_cols) {
+ if (curwin->w_virtcol < curwin->w_skipcol + overlap + scrolloff_cols) {
colnr_T col = curwin->w_virtcol;
if (col < width1) {
col += width1;
}
- while (col < curwin->w_skipcol + smoothscroll_overlap + scrolloff_cols) {
+ while (col < curwin->w_skipcol + overlap + scrolloff_cols) {
col += width2;
}
curwin->w_curswant = col;
@@ -1494,19 +1494,20 @@ void adjust_skipcol(void)
}
validate_virtcol();
+ int overlap = sms_marker_overlap(curwin, curwin_col_off() - curwin_col_off2());
while (curwin->w_skipcol > 0
- && curwin->w_virtcol < curwin->w_skipcol + 3 + scrolloff_cols) {
+ && curwin->w_virtcol < curwin->w_skipcol + overlap + scrolloff_cols) {
// scroll a screen line down
if (curwin->w_skipcol >= width1 + width2) {
curwin->w_skipcol -= width2;
} else {
curwin->w_skipcol -= width1;
}
- redraw_later(curwin, UPD_NOT_VALID);
scrolled = true;
- validate_virtcol();
}
if (scrolled) {
+ validate_virtcol();
+ redraw_later(curwin, UPD_NOT_VALID);
return; // don't scroll in the other direction now
}
long col = curwin->w_virtcol - curwin->w_skipcol + scrolloff_cols;
@@ -1870,6 +1871,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
int old_valid = curwin->w_valid;
int old_empty_rows = curwin->w_empty_rows;
linenr_T cln = curwin->w_cursor.lnum; // Cursor Line Number
+ int do_sms = curwin->w_p_wrap && curwin->w_p_sms;
if (set_topbot) {
bool set_skipcol = false;
@@ -1886,7 +1888,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
break;
}
if (used + loff.height > curwin->w_height_inner) {
- if (curwin->w_p_sms && curwin->w_p_wrap) {
+ if (do_sms) {
// 'smoothscroll' and 'wrap' are set. The above line is
// too long to show in its entirety, so we show just a part
// of it.
@@ -1925,7 +1927,6 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
used = plines_win_nofill(curwin, cln, true);
int scrolled = 0;
- int min_scrolled = 1;
// If the cursor is on or below botline, we will at least scroll by the
// height of the cursor line, which is "used". Correct for empty lines,
// which are really part of botline.
@@ -1934,16 +1935,8 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
if (cln == curwin->w_botline) {
scrolled -= curwin->w_empty_rows;
}
- min_scrolled = scrolled;
- if (curwin->w_p_sms && curwin->w_p_wrap) {
- // 'smoothscroll' and 'wrap' are set
- if (cln > curwin->w_botline) {
- // add screen lines below w_botline
- for (linenr_T lnum = curwin->w_botline + 1; lnum <= cln; lnum++) {
- min_scrolled += plines_win_nofill(curwin, lnum, true);
- }
- }
-
+ if (do_sms) {
+ // 'smoothscroll' and 'wrap' are set.
// Calculate how many screen lines the current top line of window
// occupies. If it is occupying more than the entire window, we
// need to scroll the additional clipped lines to scroll past the
@@ -1962,7 +1955,6 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
top_plines -= skip_lines;
if (top_plines > curwin->w_height_inner) {
scrolled += (top_plines - curwin->w_height_inner);
- min_scrolled += (top_plines - curwin->w_height_inner);
}
}
}
@@ -2067,21 +2059,11 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
// Otherwise put it at 1/2 of the screen.
if (line_count >= curwin->w_height_inner && line_count > min_scroll) {
scroll_cursor_halfway(false, true);
- } else {
- // With 'smoothscroll' scroll at least the height of the cursor line,
- // unless it would move the cursor.
- if (curwin->w_p_wrap && curwin->w_p_sms && line_count < min_scrolled
- && (curwin->w_cursor.lnum < curwin->w_topline
- || (curwin->w_virtcol - curwin->w_skipcol >=
- curwin->w_width_inner - curwin_col_off()))) {
- line_count = min_scrolled;
- }
- if (line_count > 0) {
- if (scrolling_screenlines(true)) {
- scrollup(scrolled, true); // TODO(vim):
- } else {
- scrollup(line_count, true);
- }
+ } else if (line_count > 0) {
+ if (do_sms) {
+ scrollup(scrolled, true); // TODO(vim):
+ } else {
+ scrollup(line_count, true);
}
}
@@ -2112,38 +2094,38 @@ void scroll_cursor_halfway(bool atend, bool prefer_above)
boff.fill = 0;
linenr_T topline = loff.lnum;
colnr_T skipcol = 0;
- bool set_skipcol = false;
- int half_height = 0;
- bool smooth_scroll = false;
- if (curwin->w_p_sms && curwin->w_p_wrap) {
+ int want_height;
+ bool do_sms = curwin->w_p_wrap && curwin->w_p_sms;
+ if (do_sms) {
// 'smoothscroll' and 'wrap' are set
- smooth_scroll = true;
- half_height = (curwin->w_height_inner - used) / 2;
- used = 0;
+ if (atend) {
+ want_height = (curwin->w_height_inner - used) / 2;
+ used = 0;
+ } else {
+ want_height = curwin->w_height_inner;
+ }
}
int topfill = 0;
while (topline > 1) {
// If using smoothscroll, we can precisely scroll to the
// exact point where the cursor is halfway down the screen.
- if (smooth_scroll) {
+ if (do_sms) {
topline_back_winheight(curwin, &loff, false);
if (loff.height == MAXCOL) {
break;
- } else {
- used += loff.height;
}
- if (used > half_height) {
- if (used - loff.height < half_height) {
- int plines_offset = used - half_height;
- loff.height -= plines_offset;
- used = half_height;
-
+ used += loff.height;
+ if (!atend && boff.lnum < curbuf->b_ml.ml_line_count) {
+ botline_forw(curwin, &boff);
+ used += boff.height;
+ }
+ if (used > want_height) {
+ if (used - loff.height < want_height) {
topline = loff.lnum;
topfill = loff.fill;
- skipcol = skipcol_from_plines(curwin, plines_offset);
- set_skipcol = true;
+ skipcol = skipcol_from_plines(curwin, used - want_height);
}
break;
}
@@ -2208,12 +2190,12 @@ void scroll_cursor_halfway(bool atend, bool prefer_above)
}
if (!hasFolding(topline, &curwin->w_topline, NULL)
- && (curwin->w_topline != topline || set_skipcol || curwin->w_skipcol != 0)) {
+ && (curwin->w_topline != topline || skipcol != 0 || curwin->w_skipcol != 0)) {
curwin->w_topline = topline;
- if (set_skipcol) {
+ if (skipcol != 0) {
curwin->w_skipcol = skipcol;
redraw_later(curwin, UPD_NOT_VALID);
- } else {
+ } else if (do_sms) {
reset_skipcol(curwin);
}
}
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 96b4bf5c3a..1772b0497b 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -110,7 +110,7 @@ static void log_client_msg(uint64_t channel_id, bool is_request, const char *nam
# define log_server_msg(...)
#endif
-static PMap(cstr_t) event_strings = MAP_INIT;
+static Set(cstr_t) event_strings = SET_INIT;
static msgpack_sbuffer out_buffer;
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -254,14 +254,12 @@ void rpc_subscribe(uint64_t id, char *event)
abort();
}
- char *event_string = pmap_get(cstr_t)(&event_strings, event);
-
- if (!event_string) {
- event_string = xstrdup(event);
- pmap_put(cstr_t)(&event_strings, event_string, event_string);
+ const char **key_alloc = NULL;
+ if (set_put_ref(cstr_t, &event_strings, event, &key_alloc)) {
+ *key_alloc = xstrdup(event);
}
- pmap_put(cstr_t)(channel->rpc.subscribed_events, event_string, event_string);
+ set_put(cstr_t, channel->rpc.subscribed_events, *key_alloc);
}
/// Unsubscribes to event broadcasts
@@ -553,9 +551,9 @@ static void broadcast_event(const char *name, Array args)
kvec_t(Channel *) subscribed = KV_INITIAL_VALUE;
Channel *channel;
- map_foreach_value(&channels, channel, {
+ pmap_foreach_value(&channels, channel, {
if (channel->is_rpc
- && pmap_has(cstr_t)(channel->rpc.subscribed_events, name)) {
+ && set_has(cstr_t, channel->rpc.subscribed_events, name)) {
kv_push(subscribed, channel);
}
});
@@ -583,24 +581,12 @@ end:
static void unsubscribe(Channel *channel, char *event)
{
- char *event_string = pmap_get(cstr_t)(&event_strings, event);
- if (!event_string) {
+ if (!set_has(cstr_t, &event_strings, event)) {
WLOG("RPC: ch %" PRIu64 ": tried to unsubscribe unknown event '%s'",
channel->id, event);
return;
}
- pmap_del(cstr_t)(channel->rpc.subscribed_events, event_string);
-
- map_foreach_value(&channels, channel, {
- if (channel->is_rpc
- && pmap_has(cstr_t)(channel->rpc.subscribed_events, event_string)) {
- return;
- }
- });
-
- // Since the string is no longer used by other channels, release it's memory
- pmap_del(cstr_t)(&event_strings, event_string);
- xfree(event_string);
+ set_del(cstr_t, channel->rpc.subscribed_events, event);
}
/// Mark rpc state as closed, and release its reference to the channel.
@@ -630,13 +616,7 @@ void rpc_free(Channel *channel)
unpacker_teardown(channel->rpc.unpacker);
xfree(channel->rpc.unpacker);
- // Unsubscribe from all events
- char *event_string;
- map_foreach_value(channel->rpc.subscribed_events, event_string, {
- unsubscribe(channel, event_string);
- });
-
- pmap_destroy(cstr_t)(channel->rpc.subscribed_events);
+ set_destroy(cstr_t, channel->rpc.subscribed_events);
kv_destroy(channel->rpc.call_stack);
api_free_dictionary(channel->rpc.info);
}
@@ -648,7 +628,7 @@ static void chan_close_with_error(Channel *channel, char *msg, int loglevel)
ChannelCallFrame *frame = kv_A(channel->rpc.call_stack, i);
frame->returned = true;
frame->errored = true;
- frame->result = STRING_OBJ(cstr_to_string(msg));
+ frame->result = CSTR_TO_OBJ(msg);
}
channel_close(channel->id, kChannelPartRpc, NULL);
@@ -685,7 +665,7 @@ static WBuffer *serialize_response(uint64_t channel_id, MsgpackRpcRequestHandler
} else {
Array args = ARRAY_DICT_INIT;
ADD(args, INTEGER_OBJ(err->type));
- ADD(args, STRING_OBJ(cstr_to_string(err->msg)));
+ ADD(args, CSTR_TO_OBJ(err->msg));
msgpack_rpc_serialize_request(0, cstr_as_string("nvim_error_event"),
args, &pac);
api_free_array(args);
@@ -734,3 +714,12 @@ const char *rpc_client_name(Channel *chan)
return NULL;
}
+
+void rpc_free_all_mem(void)
+{
+ cstr_t key;
+ set_foreach(&event_strings, key, {
+ xfree((void *)key);
+ });
+ set_destroy(cstr_t, &event_strings);
+}
diff --git a/src/nvim/msgpack_rpc/channel_defs.h b/src/nvim/msgpack_rpc/channel_defs.h
index 404e68329a..1b5f0bb298 100644
--- a/src/nvim/msgpack_rpc/channel_defs.h
+++ b/src/nvim/msgpack_rpc/channel_defs.h
@@ -31,7 +31,7 @@ typedef struct {
} RequestEvent;
typedef struct {
- PMap(cstr_t) subscribed_events[1];
+ Set(cstr_t) subscribed_events[1];
bool closed;
Unpacker *unpacker;
uint32_t next_request_id;
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 890fa0f80a..60fff45323 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -107,6 +107,8 @@ static int VIsual_mode_orig = NUL; // saved Visual mode
#endif
static const char e_changelist_is_empty[] = N_("E664: Changelist is empty");
+static const char e_cmdline_window_already_open[]
+ = N_("E1292: Command-line window is already open");
static inline void normal_state_init(NormalState *s)
{
@@ -2029,7 +2031,7 @@ static void display_showcmd(void)
if (len > 0) {
// placeholder for future highlight support
ADD_C(chunk, INTEGER_OBJ(0));
- ADD_C(chunk, STRING_OBJ(cstr_as_string(showcmd_buf)));
+ ADD_C(chunk, CSTR_AS_OBJ(showcmd_buf));
ADD_C(content, ARRAY_OBJ(chunk));
}
ui_call_msg_showcmd(content);
@@ -3232,7 +3234,7 @@ static void nv_colon(cmdarg_T *cap)
}
if (is_lua) {
- cmd_result = map_execute_lua();
+ cmd_result = map_execute_lua(true);
} else {
// get a command line and execute it
cmd_result = do_cmdline(NULL, is_cmdkey ? getcmdkeycmd : getexline, NULL,
@@ -5272,6 +5274,7 @@ static void nv_g_home_m_cmd(cmdarg_T *cap)
curwin->w_valid &= ~VALID_WCOL;
}
curwin->w_set_curswant = true;
+ adjust_skipcol();
}
/// "g_": to the last non-blank character in the line or <count> lines downward.
@@ -6371,6 +6374,10 @@ static void nv_record(cmdarg_T *cap)
}
if (cap->nchar == ':' || cap->nchar == '/' || cap->nchar == '?') {
+ if (cmdwin_type != 0) {
+ emsg(_(e_cmdline_window_already_open));
+ return;
+ }
stuffcharReadbuff(cap->nchar);
stuffcharReadbuff(K_CMDWIN);
} else {
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index bb66bb5731..de77cdd238 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -5777,6 +5777,11 @@ typedef struct {
int rv_arg; ///< extra argument
} redo_VIsual_T;
+static bool is_ex_cmdchar(cmdarg_T *cap)
+{
+ return cap->cmdchar == ':' || cap->cmdchar == K_COMMAND;
+}
+
/// Handle an operator after Visual mode or when the movement is finished.
/// "gui_yank" is true when yanking text for the clipboard.
void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
@@ -5831,7 +5836,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
if ((redo_yank || oap->op_type != OP_YANK)
&& ((!VIsual_active || oap->motion_force)
// Also redo Operator-pending Visual mode mappings.
- || ((cap->cmdchar == ':' || cap->cmdchar == K_COMMAND)
+ || ((is_ex_cmdchar(cap) || cap->cmdchar == K_LUA)
&& oap->op_type != OP_COLON))
&& cap->cmdchar != 'D'
&& oap->op_type != OP_FOLD
@@ -5851,17 +5856,24 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
AppendToRedobuffLit(cap->searchbuf, -1);
}
AppendToRedobuff(NL_STR);
- } else if (cap->cmdchar == ':' || cap->cmdchar == K_COMMAND) {
+ } else if (is_ex_cmdchar(cap)) {
// do_cmdline() has stored the first typed line in
// "repeat_cmdline". When several lines are typed repeating
// won't be possible.
if (repeat_cmdline == NULL) {
ResetRedobuff();
} else {
- AppendToRedobuffLit(repeat_cmdline, -1);
+ if (cap->cmdchar == ':') {
+ AppendToRedobuffLit(repeat_cmdline, -1);
+ } else {
+ AppendToRedobuffSpec(repeat_cmdline);
+ }
AppendToRedobuff(NL_STR);
XFREE_CLEAR(repeat_cmdline);
}
+ } else if (cap->cmdchar == K_LUA) {
+ AppendNumberToRedobuff(repeat_luaref);
+ AppendToRedobuff(NL_STR);
}
}
@@ -6017,7 +6029,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
prep_redo(oap->regname, cap->count0,
get_op_char(oap->op_type), get_extra_op_char(oap->op_type),
oap->motion_force, cap->cmdchar, cap->nchar);
- } else if (cap->cmdchar != ':' && cap->cmdchar != K_COMMAND) {
+ } else if (!is_ex_cmdchar(cap) && cap->cmdchar != K_LUA) {
int opchar = get_op_char(oap->op_type);
int extra_opchar = get_extra_op_char(oap->op_type);
int nchar = oap->op_type == OP_REPLACE ? cap->nchar : NUL;
diff --git a/src/nvim/ops.h b/src/nvim/ops.h
index 75ea1853a0..81e006be27 100644
--- a/src/nvim/ops.h
+++ b/src/nvim/ops.h
@@ -4,8 +4,8 @@
#include <stdbool.h>
#include <stddef.h>
+#include "lauxlib.h"
#include "nvim/ascii.h"
-#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/extmark.h"
@@ -126,4 +126,7 @@ static inline int op_reg_index(const int regname)
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ops.h.generated.h"
#endif
+
+EXTERN LuaRef repeat_luaref INIT(= LUA_NOREF); ///< LuaRef for "."
+
#endif // NVIM_OPS_H
diff --git a/src/nvim/option.c b/src/nvim/option.c
index fc1fc87b62..722afa64d8 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -1252,7 +1252,7 @@ static void do_set_option_string(int opt_idx, int opt_flags, char **argp, int ne
}
if (options[opt_idx].flags & P_UI_OPTION) {
ui_call_option_set(cstr_as_string(options[opt_idx].fullname),
- STRING_OBJ(cstr_as_string(saved_newval)));
+ CSTR_AS_OBJ(saved_newval));
}
}
xfree(saved_origval);
@@ -1626,7 +1626,7 @@ int do_set(char *arg, int opt_flags)
int i = (int)strlen(IObuff) + 2;
if (i + (arg - startarg) < IOSIZE) {
// append the argument with the error
- STRCAT(IObuff, ": ");
+ xstrlcat(IObuff, ": ", IOSIZE);
assert(arg >= startarg);
memmove(IObuff + i, startarg, (size_t)(arg - startarg));
IObuff[i + (arg - startarg)] = NUL;
@@ -3803,7 +3803,7 @@ void ui_refresh_options(void)
value = INTEGER_OBJ(*(long *)varp);
} else if (flags & P_STRING) {
// cstr_as_string handles NULL string
- value = STRING_OBJ(cstr_as_string(*(char **)varp));
+ value = CSTR_AS_OBJ(*(char **)varp);
}
ui_call_option_set(name, value);
}
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index dc652054e8..ed9acde2b1 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -1,7 +1,7 @@
#ifndef NVIM_OPTION_DEFS_H
#define NVIM_OPTION_DEFS_H
-#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/macros.h"
#include "nvim/types.h"
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index 1c75d5bd03..d3f676379d 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -2301,17 +2301,17 @@ static int get_encoded_char_adv(const char **p)
/// Handle setting 'listchars' or 'fillchars'.
/// Assume monocell characters
///
-/// @param value points to either the global or the window-local value.
-/// @param opt_lcs is tue for "listchars" and FALSE for "fillchars".
+/// @param value points to either the global or the window-local value.
+/// @param is_listchars is true for "listchars" and false for "fillchars".
/// @param apply if false, do not store the flags, only check for errors.
/// @return error message, NULL if it's OK.
-static const char *set_chars_option(win_T *wp, const char *value, bool opt_lcs, bool apply)
+static const char *set_chars_option(win_T *wp, const char *value, const bool is_listchars,
+ const bool apply)
{
const char *last_multispace = NULL; // Last occurrence of "multispace:"
const char *last_lmultispace = NULL; // Last occurrence of "leadmultispace:"
int multispace_len = 0; // Length of lcs-multispace string
int lead_multispace_len = 0; // Length of lcs-leadmultispace string
- const bool is_listchars = opt_lcs;
struct chars_tab {
int *cp; ///< char value
@@ -2358,13 +2358,13 @@ static const char *set_chars_option(win_T *wp, const char *value, bool opt_lcs,
if (is_listchars) {
tab = lcs_tab;
entries = ARRAY_SIZE(lcs_tab);
- if (opt_lcs && wp->w_p_lcs[0] == NUL) {
+ if (wp->w_p_lcs[0] == NUL) {
value = p_lcs; // local value is empty, use the global value
}
} else {
tab = fcs_tab;
entries = ARRAY_SIZE(fcs_tab);
- if (!opt_lcs && wp->w_p_fcs[0] == NUL) {
+ if (wp->w_p_fcs[0] == NUL) {
value = p_fcs; // local value is empty, use the global value
}
}
diff --git a/src/nvim/os/process.c b/src/nvim/os/process.c
index 2a248a1e32..98ae251e2b 100644
--- a/src/nvim/os/process.c
+++ b/src/nvim/os/process.c
@@ -254,7 +254,7 @@ Dictionary os_proc_info(int pid)
if (pe.th32ProcessID == (DWORD)pid) {
PUT(pinfo, "pid", INTEGER_OBJ(pid));
PUT(pinfo, "ppid", INTEGER_OBJ((int)pe.th32ParentProcessID));
- PUT(pinfo, "name", STRING_OBJ(cstr_to_string(pe.szExeFile)));
+ PUT(pinfo, "name", CSTR_TO_OBJ(pe.szExeFile));
}
return pinfo;
diff --git a/src/nvim/os/pty_process_win.c b/src/nvim/os/pty_process_win.c
index 2e850f8c22..a8330acd54 100644
--- a/src/nvim/os/pty_process_win.c
+++ b/src/nvim/os/pty_process_win.c
@@ -6,6 +6,7 @@
#include <stdlib.h>
#include "nvim/ascii.h"
+#include "nvim/eval/typval.h"
#include "nvim/mbyte.h" // for utf8_to_utf16, utf16_to_utf8
#include "nvim/memory.h"
#include "nvim/os/os.h"
diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c
index 5235828f7a..8b62b9e895 100644
--- a/src/nvim/os/stdpaths.c
+++ b/src/nvim/os/stdpaths.c
@@ -130,7 +130,7 @@ char *get_xdg_home(const XDGVarType idx)
xstrlcpy(IObuff, appname, appname_len + 1);
#if defined(MSWIN)
if (idx == kXDGDataHome || idx == kXDGStateHome) {
- STRCAT(IObuff, "-data");
+ xstrlcat(IObuff, "-data", IOSIZE);
}
#endif
dir = concat_fnames_realloc(dir, IObuff, true);
diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c
index 8d77e58177..0c3b254b9a 100644
--- a/src/nvim/os/time.c
+++ b/src/nvim/os/time.c
@@ -74,7 +74,7 @@ void os_delay(uint64_t ms, bool ignoreinput)
///
/// This blocks even "fast" events which is quite disruptive. This should only
/// be used in debug code. Prefer os_delay() and decide if the delay should be
-/// interupted by input or only a CTRL-C.
+/// interrupted by input or only a CTRL-C.
///
/// @see uv_sleep() (libuv v1.34.0)
///
diff --git a/src/nvim/plines.c b/src/nvim/plines.c
index 3e69e547cb..25c745ae97 100644
--- a/src/nvim/plines.c
+++ b/src/nvim/plines.c
@@ -102,12 +102,16 @@ int plines_win_nofold(win_T *wp, linenr_T lnum)
char *s;
unsigned col;
int width;
+ chartabsize_T cts;
s = ml_get_buf(wp->w_buffer, lnum, false);
- if (*s == NUL) { // empty line
- return 1;
+ init_chartabsize_arg(&cts, wp, lnum, 0, s, s);
+ if (*s == NUL && !cts.cts_has_virt_text) {
+ return 1; // be quick for an empty line
}
- col = win_linetabsize(wp, lnum, s, MAXCOL);
+ win_linetabsize_cts(&cts, (colnr_T)MAXCOL);
+ clear_chartabsize_arg(&cts);
+ col = (unsigned)cts.cts_vcol;
// If list mode is on, then the '$' at the end of the line may take up one
// extra column.
@@ -262,6 +266,11 @@ int linetabsize_col(int startcol, char *s)
while (*cts.cts_ptr != NUL) {
cts.cts_vcol += lbr_chartabsize_adv(&cts);
}
+ if (cts.cts_has_virt_text && cts.cts_ptr == cts.cts_line) {
+ // check for virtual text in an empty line
+ (void)lbr_chartabsize_adv(&cts);
+ cts.cts_vcol += cts.cts_cur_text_width_left + cts.cts_cur_text_width_right;
+ }
clear_chartabsize_arg(&cts);
return cts.cts_vcol;
}
@@ -277,10 +286,7 @@ unsigned win_linetabsize(win_T *wp, linenr_T lnum, char *line, colnr_T len)
{
chartabsize_T cts;
init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
- for (; *cts.cts_ptr != NUL && (len == MAXCOL || cts.cts_ptr < line + len);
- MB_PTR_ADV(cts.cts_ptr)) {
- cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
- }
+ win_linetabsize_cts(&cts, len);
clear_chartabsize_arg(&cts);
return (unsigned)cts.cts_vcol;
}
@@ -292,20 +298,43 @@ unsigned linetabsize(win_T *wp, linenr_T lnum)
return win_linetabsize(wp, lnum, ml_get_buf(wp->w_buffer, lnum, false), (colnr_T)MAXCOL);
}
+void win_linetabsize_cts(chartabsize_T *cts, colnr_T len)
+{
+ for (; *cts->cts_ptr != NUL && (len == MAXCOL || cts->cts_ptr < cts->cts_line + len);
+ MB_PTR_ADV(cts->cts_ptr)) {
+ cts->cts_vcol += win_lbr_chartabsize(cts, NULL);
+ }
+ // check for a virtual text on an empty line
+ if (cts->cts_has_virt_text && *cts->cts_ptr == NUL
+ && cts->cts_ptr == cts->cts_line) {
+ (void)win_lbr_chartabsize(cts, NULL);
+ cts->cts_vcol += cts->cts_cur_text_width_left + cts->cts_cur_text_width_right;
+ }
+}
+
/// Prepare the structure passed to chartabsize functions.
///
/// "line" is the start of the line, "ptr" is the first relevant character.
-/// When "lnum" is zero do not use text properties that insert text.
-void init_chartabsize_arg(chartabsize_T *cts, win_T *wp, linenr_T lnum FUNC_ATTR_UNUSED,
- colnr_T col, char *line, char *ptr)
+/// When "lnum" is zero do not use inline virtual text.
+void init_chartabsize_arg(chartabsize_T *cts, win_T *wp, linenr_T lnum, colnr_T col, char *line,
+ char *ptr)
{
cts->cts_win = wp;
cts->cts_vcol = col;
cts->cts_line = line;
cts->cts_ptr = ptr;
- cts->cts_cur_text_width = 0;
- // TODO(bfredl): actually lookup inline virtual text here
+ cts->cts_cur_text_width_left = 0;
+ cts->cts_cur_text_width_right = 0;
cts->cts_has_virt_text = false;
+ cts->cts_row = lnum - 1;
+
+ if (cts->cts_row >= 0) {
+ marktree_itr_get(wp->w_buffer->b_marktree, cts->cts_row, 0, cts->cts_iter);
+ mtkey_t mark = marktree_itr_current(cts->cts_iter);
+ if (mark.pos.row == cts->cts_row) {
+ cts->cts_has_virt_text = true;
+ }
+ }
}
/// Free any allocated item in "cts".
@@ -369,7 +398,8 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
int mb_added = 0;
int numberextra;
- cts->cts_cur_text_width = 0;
+ cts->cts_cur_text_width_left = 0;
+ cts->cts_cur_text_width_right = 0;
// No 'linebreak', 'showbreak' and 'breakindent': return quickly.
if (!wp->w_p_lbr && !wp->w_p_bri && *get_showbreak_value(wp) == NUL
@@ -383,7 +413,34 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
// First get normal size, without 'linebreak' or virtual text
int size = win_chartabsize(wp, s, vcol);
if (cts->cts_has_virt_text) {
- // TODO(bfredl): inline virtual text
+ int tab_size = size;
+ int charlen = *s == NUL ? 1 : utf_ptr2len(s);
+ int col = (int)(s - line);
+ while (true) {
+ mtkey_t mark = marktree_itr_current(cts->cts_iter);
+ if (mark.pos.row != cts->cts_row || mark.pos.col > col) {
+ break;
+ } else if (mark.pos.col >= col && mark.pos.col < col + charlen) {
+ if (!mt_end(mark)) {
+ Decoration decor = get_decor(mark);
+ if (decor.virt_text_pos == kVTInline) {
+ if (mt_right(mark)) {
+ cts->cts_cur_text_width_right += decor.virt_text_width;
+ } else {
+ cts->cts_cur_text_width_left += decor.virt_text_width;
+ }
+ size += decor.virt_text_width;
+ if (*s == TAB) {
+ // tab size changes because of the inserted text
+ size -= tab_size;
+ tab_size = win_chartabsize(wp, s, vcol + size);
+ size += tab_size;
+ }
+ }
+ }
+ }
+ marktree_itr_next(wp->w_buffer->b_marktree, cts->cts_iter);
+ }
}
int c = (uint8_t)(*s);
diff --git a/src/nvim/plines.h b/src/nvim/plines.h
index 808f6d284e..2ce7133705 100644
--- a/src/nvim/plines.h
+++ b/src/nvim/plines.h
@@ -11,10 +11,12 @@ typedef struct {
win_T *cts_win;
char *cts_line; // start of the line
char *cts_ptr; // current position in line
+ int cts_row;
bool cts_has_virt_text; // true if if a property inserts text
- int cts_cur_text_width; // width of current inserted text
- // TODO(bfredl): iterator in to the marktree for scanning virt text
+ int cts_cur_text_width_left; // width of virtual text left of cursor
+ int cts_cur_text_width_right; // width of virtual text right of cursor
+ MarkTreeIter cts_iter[1];
int cts_vcol; // virtual column at current position
} chartabsize_T;
diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c
index d404aa9647..15d0372c6f 100644
--- a/src/nvim/popupmenu.c
+++ b/src/nvim/popupmenu.c
@@ -164,10 +164,10 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
Array arr = arena_array(&arena, (size_t)size);
for (int i = 0; i < size; i++) {
Array item = arena_array(&arena, 4);
- ADD_C(item, STRING_OBJ(cstr_as_string(array[i].pum_text)));
- ADD_C(item, STRING_OBJ(cstr_as_string(array[i].pum_kind)));
- ADD_C(item, STRING_OBJ(cstr_as_string(array[i].pum_extra)));
- ADD_C(item, STRING_OBJ(cstr_as_string(array[i].pum_info)));
+ ADD_C(item, CSTR_AS_OBJ(array[i].pum_text));
+ ADD_C(item, CSTR_AS_OBJ(array[i].pum_kind));
+ ADD_C(item, CSTR_AS_OBJ(array[i].pum_extra));
+ ADD_C(item, CSTR_AS_OBJ(array[i].pum_info));
ADD_C(arr, ARRAY_OBJ(item));
}
ui_call_popupmenu_show(arr, selected, pum_win_row, cursor_col,
@@ -1083,7 +1083,7 @@ void pum_show_popupmenu(vimmenu_T *menu)
// When there are only Terminal mode menus, using "popup Edit" results in
// pum_size being zero.
if (pum_size <= 0) {
- emsg(e_menuothermode);
+ emsg(_(e_menu_only_exists_in_another_mode));
return;
}
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index b4a23d544e..4b27067fb8 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -512,7 +512,7 @@ Array runtime_inspect(void)
for (size_t i = 0; i < kv_size(path); i++) {
SearchPathItem *item = &kv_A(path, i);
Array entry = ARRAY_DICT_INIT;
- ADD(entry, STRING_OBJ(cstr_to_string(item->path)));
+ ADD(entry, CSTR_TO_OBJ(item->path));
ADD(entry, BOOLEAN_OBJ(item->after));
if (item->has_lua != kNone) {
ADD(entry, BOOLEAN_OBJ(item->has_lua == kTrue));
@@ -568,7 +568,7 @@ ArrayOf(String) runtime_get_named_common(bool lua, Array pat, bool all,
item->path, pat_item.data.string.data);
if (size < buf_len) {
if (os_file_is_readable(buf)) {
- ADD(rv, STRING_OBJ(cstr_to_string(buf)));
+ ADD(rv, CSTR_TO_OBJ(buf));
if (!all) {
goto done;
}
@@ -646,21 +646,20 @@ int do_in_path_and_pp(char *path, char *name, int flags, DoInRuntimepathCB callb
return done;
}
-static void push_path(RuntimeSearchPath *search_path, Map(String, handle_T) *rtp_used, char *entry,
+static void push_path(RuntimeSearchPath *search_path, Set(String) *rtp_used, char *entry,
bool after)
{
- handle_T h = map_get(String, handle_T)(rtp_used, cstr_as_string(entry));
- if (h == 0) {
- char *allocated = xstrdup(entry);
- map_put(String, handle_T)(rtp_used, cstr_as_string(allocated), 1);
- kv_push(*search_path, ((SearchPathItem){ allocated, after, kNone }));
+ String *key_alloc;
+ if (set_put_ref(String, rtp_used, cstr_as_string(entry), &key_alloc)) {
+ *key_alloc = cstr_to_string(entry);
+ kv_push(*search_path, ((SearchPathItem){ key_alloc->data, after, kNone }));
}
}
-static void expand_rtp_entry(RuntimeSearchPath *search_path, Map(String, handle_T) *rtp_used,
- char *entry, bool after)
+static void expand_rtp_entry(RuntimeSearchPath *search_path, Set(String) *rtp_used, char *entry,
+ bool after)
{
- if (map_get(String, handle_T)(rtp_used, cstr_as_string(entry))) {
+ if (set_has(String, rtp_used, cstr_as_string(entry))) {
return;
}
@@ -679,7 +678,7 @@ static void expand_rtp_entry(RuntimeSearchPath *search_path, Map(String, handle_
}
}
-static void expand_pack_entry(RuntimeSearchPath *search_path, Map(String, handle_T) *rtp_used,
+static void expand_pack_entry(RuntimeSearchPath *search_path, Set(String) *rtp_used,
CharVec *after_path, char *pack_entry, size_t pack_entry_len)
{
static char buf[MAXPATHL];
@@ -712,10 +711,8 @@ static bool path_is_after(char *buf, size_t buflen)
RuntimeSearchPath runtime_search_path_build(void)
{
kvec_t(String) pack_entries = KV_INITIAL_VALUE;
- // TODO(bfredl): these should just be sets, when Set(String) is do merge to
- // master.
Map(String, handle_T) pack_used = MAP_INIT;
- Map(String, handle_T) rtp_used = MAP_INIT;
+ Set(String) rtp_used = SET_INIT;
RuntimeSearchPath search_path = KV_INITIAL_VALUE;
CharVec after_path = KV_INITIAL_VALUE;
@@ -744,7 +741,7 @@ RuntimeSearchPath runtime_search_path_build(void)
// fact: &rtp entries can contain wild chars
expand_rtp_entry(&search_path, &rtp_used, buf, false);
- handle_T *h = map_ref(String, handle_T)(&pack_used, cstr_as_string(buf), false);
+ handle_T *h = map_ref(String, handle_T)(&pack_used, cstr_as_string(buf), NULL);
if (h) {
(*h)++;
expand_pack_entry(&search_path, &rtp_used, &after_path, buf, buflen);
@@ -774,8 +771,8 @@ RuntimeSearchPath runtime_search_path_build(void)
// strings are not owned
kv_destroy(pack_entries);
kv_destroy(after_path);
- map_destroy(String, handle_T)(&pack_used);
- map_destroy(String, handle_T)(&rtp_used);
+ map_destroy(String, &pack_used);
+ set_destroy(String, &rtp_used);
return search_path;
}
@@ -1547,7 +1544,7 @@ static inline char *add_dir(char *dest, const char *const dir, const size_t dir_
xstrlcpy(IObuff, appname, appname_len + 1);
#if defined(MSWIN)
if (type == kXDGDataHome || type == kXDGStateHome) {
- STRCAT(IObuff, "-data");
+ xstrlcat(IObuff, "-data", IOSIZE);
appname_len += 5;
}
#endif
@@ -2409,7 +2406,7 @@ void f_getscriptinfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
if (sid <= 0) {
- semsg(e_invargNval, "sid", tv_get_string(&sid_di->di_tv));
+ semsg(_(e_invargNval), "sid", tv_get_string(&sid_di->di_tv));
return;
}
} else {
diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h
index 9a810298f8..188ff7b36c 100644
--- a/src/nvim/runtime.h
+++ b/src/nvim/runtime.h
@@ -5,7 +5,6 @@
#include "klib/kvec.h"
#include "nvim/autocmd.h"
-#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_eval_defs.h"
diff --git a/src/nvim/search.c b/src/nvim/search.c
index d1a31a357f..bcaacede9e 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -1519,7 +1519,7 @@ int searchc(cmdarg_T *cap, int t_cmd)
}
}
} else { // repeat previous search
- if (*lastc == NUL && lastc_bytelen == 1) {
+ if (*lastc == NUL && lastc_bytelen <= 1) {
return FAIL;
}
if (dir) { // repeat in opposite direction
@@ -1562,7 +1562,7 @@ int searchc(cmdarg_T *cap, int t_cmd)
}
col -= utf_head_off(p, p + col - 1) + 1;
}
- if (lastc_bytelen == 1) {
+ if (lastc_bytelen <= 1) {
if (p[col] == c && stop) {
break;
}
diff --git a/src/nvim/search.h b/src/nvim/search.h
index 2f140ba840..eeff9f8744 100644
--- a/src/nvim/search.h
+++ b/src/nvim/search.h
@@ -5,7 +5,6 @@
#include <stdint.h>
#include "nvim/buffer_defs.h"
-#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/normal.h"
#include "nvim/os/time.h"
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index c405b8ca5f..db911f4bfd 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -16,7 +16,6 @@
#include <uv.h>
#include "auto/config.h"
-#include "klib/khash.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/ascii.h"
@@ -35,6 +34,7 @@
#include "nvim/globals.h"
#include "nvim/hashtab.h"
#include "nvim/macros.h"
+#include "nvim/map.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
@@ -62,19 +62,6 @@
# include ENDIAN_INCLUDE_FILE
#endif
-// Note: when using bufset hash pointers are intentionally casted to uintptr_t
-// and not to khint32_t or khint64_t: this way compiler must give a warning
-// (-Wconversion) when types change.
-#ifdef ARCH_32
-KHASH_SET_INIT_INT(bufset)
-#elif defined(ARCH_64)
-KHASH_SET_INIT_INT64(bufset)
-#else
-# error Not a 64- or 32-bit architecture
-#endif
-KHASH_MAP_INIT_STR(fnamebufs, buf_T *)
-KHASH_SET_INIT_STR(strset)
-
#define SEARCH_KEY_MAGIC "sm"
#define SEARCH_KEY_SMARTCASE "sc"
#define SEARCH_KEY_HAS_LINE_OFFSET "sl"
@@ -305,8 +292,6 @@ typedef struct hm_llist_entry {
struct hm_llist_entry *prev; ///< Pointer to previous entry or NULL.
} HMLListEntry;
-KHASH_MAP_INIT_STR(hmll_entries, HMLListEntry *)
-
/// Sized linked list structure for history merger
typedef struct {
HMLListEntry *entries; ///< Pointer to the start of the allocated array of
@@ -318,9 +303,8 @@ typedef struct {
HMLListEntry *last_free_entry; ///< Last unused element in entries array.
size_t size; ///< Number of allocated entries.
size_t num_entries; ///< Number of entries already used.
- khash_t(hmll_entries) contained_entries; ///< Hash mapping all history entry
- ///< strings to corresponding entry
- ///< pointers.
+ PMap(cstr_t) contained_entries; ///< Map all history entry strings to
+ ///< corresponding entry pointers.
} HMLList;
typedef struct {
@@ -348,8 +332,6 @@ typedef struct {
Timestamp greatest_timestamp; ///< Greatest timestamp among marks.
} FileMarks;
-KHASH_MAP_INIT_STR(file_marks, FileMarks)
-
/// State structure used by shada_write
///
/// Before actually writing most of the data is read to this structure.
@@ -363,8 +345,8 @@ typedef struct {
PossiblyFreedShadaEntry search_pattern; ///< Last search pattern.
PossiblyFreedShadaEntry sub_search_pattern; ///< Last s/ search pattern.
PossiblyFreedShadaEntry replacement; ///< Last s// replacement string.
- khash_t(strset) dumped_variables; ///< Names of already dumped variables.
- khash_t(file_marks) file_marks; ///< All file marks.
+ Set(cstr_t) dumped_variables; ///< Names of already dumped variables.
+ PMap(cstr_t) file_marks; ///< All file marks.
} WriteMergerState;
struct sd_read_def;
@@ -504,7 +486,7 @@ static inline void hmll_init(HMLList *const hmll, const size_t size)
.free_entry = NULL,
.size = size,
.num_entries = 0,
- .contained_entries = KHASH_EMPTY_TABLE(hmll_entries),
+ .contained_entries = MAP_INIT,
};
hmll->last_free_entry = hmll->entries;
}
@@ -535,10 +517,10 @@ static inline void hmll_remove(HMLList *const hmll, HMLListEntry *const hmll_ent
assert(hmll->free_entry == NULL);
hmll->free_entry = hmll_entry;
}
- const khiter_t k = kh_get(hmll_entries, &hmll->contained_entries,
- hmll_entry->data.data.history_item.string);
- assert(k != kh_end(&hmll->contained_entries));
- kh_del(hmll_entries, &hmll->contained_entries, k);
+ ptr_t val = pmap_del(cstr_t)(&hmll->contained_entries,
+ hmll_entry->data.data.history_item.string, NULL);
+ assert(val);
+ (void)val;
if (hmll_entry->next == NULL) {
hmll->last = hmll_entry->prev;
} else {
@@ -586,11 +568,11 @@ static inline void hmll_insert(HMLList *const hmll, HMLListEntry *hmll_entry, co
}
target_entry->data = data;
target_entry->can_free_entry = can_free_entry;
- int kh_ret;
- const khiter_t k = kh_put(hmll_entries, &hmll->contained_entries,
- data.data.history_item.string, &kh_ret);
- if (kh_ret > 0) {
- kh_val(&hmll->contained_entries, k) = target_entry;
+ bool new_item = false;
+ ptr_t *val = pmap_put_ref(cstr_t)(&hmll->contained_entries, data.data.history_item.string,
+ NULL, &new_item);
+ if (new_item) {
+ *val = target_entry;
}
hmll->num_entries++;
target_entry->prev = hmll_entry;
@@ -614,7 +596,7 @@ static inline void hmll_insert(HMLList *const hmll, HMLListEntry *hmll_entry, co
static inline void hmll_dealloc(HMLList *const hmll)
FUNC_ATTR_NONNULL_ALL
{
- kh_dealloc(hmll_entries, &hmll->contained_entries);
+ map_destroy(cstr_t, &hmll->contained_entries);
xfree(hmll->entries);
}
@@ -771,30 +753,6 @@ static void close_file(void *cookie)
}
}
-/// Check whether buffer is in the given set
-///
-/// @param[in] set Set to check within.
-/// @param[in] buf Buffer to find.
-///
-/// @return true or false.
-static inline bool in_bufset(const khash_t(bufset) *const set, const buf_T *buf)
- FUNC_ATTR_PURE
-{
- return kh_get(bufset, set, (uintptr_t)buf) != kh_end(set);
-}
-
-/// Check whether string is in the given set
-///
-/// @param[in] set Set to check within.
-/// @param[in] buf Buffer to find.
-///
-/// @return true or false.
-static inline bool in_strset(const khash_t(strset) *const set, char *str)
- FUNC_ATTR_PURE
-{
- return kh_get(strset, set, str) != kh_end(set);
-}
-
/// Msgpack callback for writing to ShaDaWriteDef*
static int msgpack_sd_writer_write(void *data, const char *buf, size_t len)
{
@@ -930,10 +888,11 @@ static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry,
}
}
HMLList *const hmll = &hms_p->hmll;
- const khiter_t k = kh_get(hmll_entries, &hms_p->hmll.contained_entries,
- entry.data.history_item.string);
- if (k != kh_end(&hmll->contained_entries)) {
- HMLListEntry *const existing_entry = kh_val(&hmll->contained_entries, k);
+ cstr_t *key_alloc = NULL;
+ ptr_t *val = pmap_ref(cstr_t)(&hms_p->hmll.contained_entries, entry.data.history_item.string,
+ &key_alloc);
+ if (val) {
+ HMLListEntry *const existing_entry = *val;
if (entry.timestamp > existing_entry->data.timestamp) {
hmll_remove(hmll, existing_entry);
} else if (!do_iter && entry.timestamp == existing_entry->data.timestamp) {
@@ -944,7 +903,7 @@ static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry,
existing_entry->data = entry;
existing_entry->can_free_entry = can_free_entry;
// Previous key was freed above, as part of freeing the ShaDa entry.
- kh_key(&hmll->contained_entries, k) = entry.data.history_item.string;
+ *key_alloc = entry.data.history_item.string;
return;
} else {
return;
@@ -1046,24 +1005,27 @@ static inline void hms_dealloc(HistoryMergerState *const hms_p)
/// @param[in] fname File name to find.
///
/// @return Pointer to the buffer or NULL.
-static buf_T *find_buffer(khash_t(fnamebufs) *const fname_bufs, const char *const fname)
+static buf_T *find_buffer(PMap(cstr_t) *const fname_bufs, const char *const fname)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- int kh_ret;
- khint_t k = kh_put(fnamebufs, fname_bufs, fname, &kh_ret);
- if (!kh_ret) {
- return kh_val(fname_bufs, k);
+ cstr_t *key_alloc = NULL;
+ bool new_item = false;
+ buf_T **ref = (buf_T **)pmap_put_ref(cstr_t)(fname_bufs, fname, &key_alloc, &new_item);
+ if (new_item) {
+ *key_alloc = xstrdup(fname);
+ } else {
+ return *ref; // item already existed (can be a NULL value)
}
- kh_key(fname_bufs, k) = xstrdup(fname);
+
FOR_ALL_BUFFERS(buf) {
if (buf->b_ffname != NULL) {
if (path_fnamecmp(fname, buf->b_ffname) == 0) {
- kh_val(fname_bufs, k) = buf;
+ *ref = buf;
return buf;
}
}
}
- kh_val(fname_bufs, k) = NULL;
+ *ref = NULL;
return NULL;
}
@@ -1163,9 +1125,9 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
}
}
ShadaEntry cur_entry;
- khash_t(bufset) cl_bufs = KHASH_EMPTY_TABLE(bufset);
- khash_t(fnamebufs) fname_bufs = KHASH_EMPTY_TABLE(fnamebufs);
- khash_t(strset) oldfiles_set = KHASH_EMPTY_TABLE(strset);
+ Set(ptr_t) cl_bufs = SET_INIT;
+ PMap(cstr_t) fname_bufs = MAP_INIT;
+ Set(cstr_t) oldfiles_set = SET_INIT;
if (get_old_files && (oldfiles_list == NULL || force)) {
oldfiles_list = tv_list_alloc(kListLenUnknown);
set_vim_var_list(VV_OLDFILES, oldfiles_list);
@@ -1359,8 +1321,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
break;
case kSDItemChange:
case kSDItemLocalMark: {
- if (get_old_files && !in_strset(&oldfiles_set,
- cur_entry.data.filemark.fname)) {
+ if (get_old_files && !set_has(cstr_t, &oldfiles_set, cur_entry.data.filemark.fname)) {
char *fname = cur_entry.data.filemark.fname;
if (want_marks) {
// Do not bother with allocating memory for the string if already
@@ -1368,8 +1329,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
// want_marks is set because this way it may be used for a mark.
fname = xstrdup(fname);
}
- int kh_ret;
- (void)kh_put(strset, &oldfiles_set, fname, &kh_ret);
+ set_put(cstr_t, &oldfiles_set, fname);
tv_list_append_allocated_string(oldfiles_list, fname);
if (!want_marks) {
// Avoid free because this string was already used.
@@ -1398,8 +1358,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
break;
}
} else {
- int kh_ret;
- (void)kh_put(bufset, &cl_bufs, (uintptr_t)buf, &kh_ret);
+ set_put(ptr_t, &cl_bufs, buf);
#define SDE_TO_FMARK(entry) fm
#define AFTERFREE(entry) (entry).data.filemark.fname = NULL
#define DUMMY_IDX_ADJ(i)
@@ -1440,18 +1399,18 @@ shada_read_main_cycle_end:
if (cl_bufs.n_occupied) {
FOR_ALL_TAB_WINDOWS(tp, wp) {
(void)tp;
- if (in_bufset(&cl_bufs, wp->w_buffer)) {
+ if (set_has(ptr_t, &cl_bufs, wp->w_buffer)) {
wp->w_changelistidx = wp->w_buffer->b_changelistlen;
}
}
}
- kh_dealloc(bufset, &cl_bufs);
+ set_destroy(ptr_t, &cl_bufs);
const char *key;
- kh_foreach_key(&fname_bufs, key, {
- xfree((void *)key);
+ map_foreach_key(&fname_bufs, key, {
+ xfree((char *)key);
})
- kh_dealloc(fnamebufs, &fname_bufs);
- kh_dealloc(strset, &oldfiles_set);
+ map_destroy(cstr_t, &fname_bufs);
+ set_destroy(cstr_t, &oldfiles_set);
}
/// Default shada file location: cached path
@@ -2154,7 +2113,7 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re
break;
}
case kSDItemVariable:
- if (!in_strset(&wms->dumped_variables, entry.data.global_var.name)) {
+ if (!set_has(cstr_t, &wms->dumped_variables, entry.data.global_var.name)) {
ret = shada_pack_entry(packer, entry, 0);
}
shada_free_shada_entry(&entry);
@@ -2211,13 +2170,12 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re
break;
}
const char *const fname = entry.data.filemark.fname;
- khiter_t k;
- int kh_ret;
- k = kh_put(file_marks, &wms->file_marks, fname, &kh_ret);
- FileMarks *const filemarks = &kh_val(&wms->file_marks, k);
- if (kh_ret > 0) {
- CLEAR_POINTER(filemarks);
+ cstr_t *key = NULL;
+ ptr_t *val = pmap_put_ref(cstr_t)(&wms->file_marks, fname, &key, NULL);
+ if (*val == NULL) {
+ *val = xcalloc(1, sizeof(FileMarks));
}
+ FileMarks *const filemarks = *val;
if (entry.timestamp > filemarks->greatest_timestamp) {
filemarks->greatest_timestamp = entry.timestamp;
}
@@ -2237,9 +2195,8 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re
break;
}
if (wms_entry->can_free_entry) {
- if (kh_key(&wms->file_marks, k)
- == wms_entry->data.data.filemark.fname) {
- kh_key(&wms->file_marks, k) = entry.data.filemark.fname;
+ if (*key == wms_entry->data.data.filemark.fname) {
+ *key = entry.data.filemark.fname;
}
shada_free_shada_entry(&wms_entry->data);
}
@@ -2281,11 +2238,11 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re
/// @param[in] removable_bufs Cache of buffers ignored due to their location.
///
/// @return true or false.
-static inline bool ignore_buf(const buf_T *const buf, khash_t(bufset) *const removable_bufs)
+static inline bool ignore_buf(const buf_T *const buf, Set(ptr_t) *const removable_bufs)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE
{
return (buf->b_ffname == NULL || !buf->b_p_bl || bt_quickfix(buf) \
- || bt_terminal(buf) || in_bufset(removable_bufs, buf));
+ || bt_terminal(buf) || set_has(ptr_t, removable_bufs, (ptr_t)buf));
}
/// Get list of buffers to write to the shada file
@@ -2293,7 +2250,7 @@ static inline bool ignore_buf(const buf_T *const buf, khash_t(bufset) *const rem
/// @param[in] removable_bufs Buffers which are ignored
///
/// @return ShadaEntry List of buffers to save, kSDItemBufferList entry.
-static inline ShadaEntry shada_get_buflist(khash_t(bufset) *const removable_bufs)
+static inline ShadaEntry shada_get_buflist(Set(ptr_t) *const removable_bufs)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE
{
int max_bufs = get_shada_parameter('%');
@@ -2461,12 +2418,11 @@ static inline void replace_numbered_mark(WriteMergerState *const wms, const size
/// Find buffers ignored due to their location.
///
/// @param[out] removable_bufs Cache of buffers ignored due to their location.
-static inline void find_removable_bufs(khash_t(bufset) *removable_bufs)
+static inline void find_removable_bufs(Set(ptr_t) *removable_bufs)
{
FOR_ALL_BUFFERS(buf) {
if (buf->b_ffname != NULL && shada_removable(buf->b_ffname)) {
- int kh_ret;
- (void)kh_put(bufset, removable_bufs, (uintptr_t)buf, &kh_ret);
+ set_put(ptr_t, removable_bufs, (ptr_t)buf);
}
}
}
@@ -2518,7 +2474,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef
max_reg_lines = get_shada_parameter('"');
}
const bool dump_registers = (max_reg_lines != 0);
- khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset);
+ Set(ptr_t) removable_bufs = SET_INIT;
const size_t max_kbyte = (size_t)max_kbyte_i;
const size_t num_marked_files = (size_t)get_shada_parameter('\'');
const bool dump_global_marks = get_shada_parameter('f') != 0;
@@ -2573,15 +2529,15 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef
.capacity = 5,
.items = ((KeyValuePair[]) {
{ STATIC_CSTR_AS_STRING("generator"),
- STRING_OBJ(STATIC_CSTR_AS_STRING("nvim")) },
+ STATIC_CSTR_AS_OBJ("nvim") },
{ STATIC_CSTR_AS_STRING("version"),
- STRING_OBJ(cstr_as_string(longVersion)) },
+ CSTR_AS_OBJ(longVersion) },
{ STATIC_CSTR_AS_STRING("max_kbyte"),
INTEGER_OBJ((Integer)max_kbyte) },
{ STATIC_CSTR_AS_STRING("pid"),
INTEGER_OBJ((Integer)os_get_pid()) },
{ STATIC_CSTR_AS_STRING("encoding"),
- STRING_OBJ(cstr_as_string(p_enc)) },
+ CSTR_AS_OBJ(p_enc) },
}),
}
}
@@ -2662,8 +2618,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef
tv_clear(&vartv);
tv_clear(&tgttv);
if (spe_ret == kSDWriteSuccessful) {
- int kh_ret;
- (void)kh_put(strset, &wms->dumped_variables, name, &kh_ret);
+ set_put(cstr_t, &wms->dumped_variables, name);
}
} while (var_iter != NULL);
}
@@ -2723,7 +2678,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef
} else {
const buf_T *const buf = buflist_findnr(fm.fmark.fnum);
if (buf == NULL || buf->b_ffname == NULL
- || in_bufset(&removable_bufs, buf)) {
+ || set_has(ptr_t, &removable_bufs, (ptr_t)buf)) {
continue;
}
fname = buf->b_ffname;
@@ -2759,18 +2714,16 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef
// Initialize buffers
if (num_marked_files > 0) {
FOR_ALL_BUFFERS(buf) {
- if (buf->b_ffname == NULL || in_bufset(&removable_bufs, buf)) {
+ if (buf->b_ffname == NULL || set_has(ptr_t, &removable_bufs, buf)) {
continue;
}
const void *local_marks_iter = NULL;
const char *const fname = buf->b_ffname;
- khiter_t k;
- int kh_ret;
- k = kh_put(file_marks, &wms->file_marks, fname, &kh_ret);
- FileMarks *const filemarks = &kh_val(&wms->file_marks, k);
- if (kh_ret > 0) {
- CLEAR_POINTER(filemarks);
+ ptr_t *val = pmap_put_ref(cstr_t)(&wms->file_marks, fname, NULL, NULL);
+ if (*val == NULL) {
+ *val = xcalloc(1, sizeof(FileMarks));
}
+ FileMarks *const filemarks = *val;
do {
fmark_T fm;
char name = NUL;
@@ -2887,16 +2840,14 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef
PACK_WMS_ENTRY(wms->replacement);
#undef PACK_WMS_ENTRY
- const size_t file_markss_size = kh_size(&wms->file_marks);
+ const size_t file_markss_size = map_size(&wms->file_marks);
FileMarks **const all_file_markss =
xmalloc(file_markss_size * sizeof(*all_file_markss));
FileMarks **cur_file_marks = all_file_markss;
- for (khint_t i = kh_begin(&wms->file_marks); i != kh_end(&wms->file_marks);
- i++) {
- if (kh_exist(&wms->file_marks, i)) {
- *cur_file_marks++ = &kh_val(&wms->file_marks, i);
- }
- }
+ ptr_t val;
+ map_foreach_value(ptr_t, &wms->file_marks, val, {
+ *cur_file_marks++ = val;
+ })
qsort((void *)all_file_markss, file_markss_size, sizeof(*all_file_markss),
&compare_file_marks);
const size_t file_markss_to_dump = MIN(num_marked_files, file_markss_size);
@@ -2949,10 +2900,13 @@ shada_write_exit:
hms_dealloc(&wms->hms[i]);
}
}
- kh_dealloc(file_marks, &wms->file_marks);
- kh_dealloc(bufset, &removable_bufs);
+ map_foreach_value(ptr_t, &wms->file_marks, val, {
+ xfree(val);
+ })
+ map_destroy(cstr_t, &wms->file_marks);
+ set_destroy(ptr_t, &removable_bufs);
msgpack_packer_free(packer);
- kh_dealloc(strset, &wms->dumped_variables);
+ set_destroy(cstr_t, &wms->dumped_variables);
xfree(wms);
return ret;
}
@@ -4035,7 +3989,7 @@ static bool shada_removable(const char *name)
///
/// @return number of jumplist entries
static inline size_t shada_init_jumps(PossiblyFreedShadaEntry *jumps,
- khash_t(bufset) *const removable_bufs)
+ Set(ptr_t) *const removable_bufs)
{
// Initialize jump list
size_t jumps_size = 0;
@@ -4056,7 +4010,7 @@ static inline size_t shada_init_jumps(PossiblyFreedShadaEntry *jumps,
? NULL
: buflist_findnr(fm.fmark.fnum));
if (buf != NULL
- ? in_bufset(removable_bufs, buf)
+ ? set_has(ptr_t, removable_bufs, (ptr_t)buf)
: fm.fmark.fnum != 0) {
continue;
}
@@ -4111,7 +4065,7 @@ void shada_encode_regs(msgpack_sbuffer *const sbuf)
void shada_encode_jumps(msgpack_sbuffer *const sbuf)
FUNC_ATTR_NONNULL_ALL
{
- khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset);
+ Set(ptr_t) removable_bufs = SET_INIT;
find_removable_bufs(&removable_bufs);
PossiblyFreedShadaEntry jumps[JUMPLISTSIZE];
size_t jumps_size = shada_init_jumps(jumps, &removable_bufs);
@@ -4130,7 +4084,7 @@ void shada_encode_jumps(msgpack_sbuffer *const sbuf)
void shada_encode_buflist(msgpack_sbuffer *const sbuf)
FUNC_ATTR_NONNULL_ALL
{
- khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset);
+ Set(ptr_t) removable_bufs = SET_INIT;
find_removable_bufs(&removable_bufs);
ShadaEntry buflist_entry = shada_get_buflist(&removable_bufs);
msgpack_packer packer;
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 84875261f1..778266e5ac 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -1189,11 +1189,19 @@ bool spell_valid_case(int wordflags, int treeflags)
|| (wordflags & WF_ONECAP) != 0));
}
-// Returns true if spell checking is not enabled.
+/// Return true if spell checking is enabled for "wp".
+bool spell_check_window(win_T *wp)
+{
+ return wp->w_p_spell
+ && *wp->w_s->b_p_spl != NUL
+ && wp->w_s->b_langp.ga_len > 0
+ && *(char **)(wp->w_s->b_langp.ga_data) != NULL;
+}
+
+/// Return true and give an error if spell checking is not enabled.
bool no_spell_checking(win_T *wp)
{
- if (!wp->w_p_spell || *wp->w_s->b_p_spl == NUL
- || GA_EMPTY(&wp->w_s->b_langp)) {
+ if (!wp->w_p_spell || *wp->w_s->b_p_spl == NUL || GA_EMPTY(&wp->w_s->b_langp)) {
emsg(_(e_no_spell));
return true;
}
@@ -1304,7 +1312,7 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
} else if (curline && wp == curwin) {
// For spellbadword(): check if first word needs a capital.
col = (colnr_T)getwhitecols(line);
- if (check_need_cap(lnum, col)) {
+ if (check_need_cap(curwin, lnum, col)) {
capcol = col;
}
@@ -2528,25 +2536,24 @@ int spell_casefold(const win_T *wp, char *str, int len, char *buf, int buflen)
}
// Check if the word at line "lnum" column "col" is required to start with a
-// capital. This uses 'spellcapcheck' of the current buffer.
-bool check_need_cap(linenr_T lnum, colnr_T col)
+// capital. This uses 'spellcapcheck' of the buffer in window "wp".
+bool check_need_cap(win_T *wp, linenr_T lnum, colnr_T col)
{
- bool need_cap = false;
-
- if (curwin->w_s->b_cap_prog == NULL) {
+ if (wp->w_s->b_cap_prog == NULL) {
return false;
}
- char *line = get_cursor_line_ptr();
+ bool need_cap = false;
+ char *line = col ? ml_get_buf(wp->w_buffer, lnum, false) : NULL;
char *line_copy = NULL;
colnr_T endcol = 0;
- if (getwhitecols(line) >= (int)col) {
+ if (col == 0 || getwhitecols(line) >= col) {
// At start of line, check if previous line is empty or sentence
// ends there.
if (lnum == 1) {
need_cap = true;
} else {
- line = ml_get(lnum - 1);
+ line = ml_get_buf(wp->w_buffer, lnum - 1, false);
if (*skipwhite(line) == NUL) {
need_cap = true;
} else {
@@ -2563,13 +2570,13 @@ bool check_need_cap(linenr_T lnum, colnr_T col)
if (endcol > 0) {
// Check if sentence ends before the bad word.
regmatch_T regmatch = {
- .regprog = curwin->w_s->b_cap_prog,
+ .regprog = wp->w_s->b_cap_prog,
.rm_ic = false
};
char *p = line + endcol;
while (true) {
MB_PTR_BACK(line, p);
- if (p == line || spell_iswordp_nmw(p, curwin)) {
+ if (p == line || spell_iswordp_nmw(p, wp)) {
break;
}
if (vim_regexec(&regmatch, p, 0)
@@ -2578,7 +2585,7 @@ bool check_need_cap(linenr_T lnum, colnr_T col)
break;
}
}
- curwin->w_s->b_cap_prog = regmatch.regprog;
+ wp->w_s->b_cap_prog = regmatch.regprog;
}
xfree(line_copy);
@@ -3593,7 +3600,7 @@ static bool spell_expand_need_cap;
void spell_expand_check_cap(colnr_T col)
{
- spell_expand_need_cap = check_need_cap(curwin->w_cursor.lnum, col);
+ spell_expand_need_cap = check_need_cap(curwin, curwin->w_cursor.lnum, col);
}
// Get list of spelling suggestions.
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index 5e4a429cc7..e81cebe18a 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -3131,7 +3131,7 @@ static int spell_read_dic(spellinfo_T *spin, char *fname, afffile_T *affile)
// Remove CR, LF and white space from the end. White space halfway through
// the word is kept to allow multi-word terms like "et al.".
l = (int)strlen(line);
- while (l > 0 && line[l - 1] <= ' ') {
+ while (l > 0 && (uint8_t)line[l - 1] <= ' ') {
l--;
}
if (l == 0) {
diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c
index 84be88be7b..1c34c2487f 100644
--- a/src/nvim/spellsuggest.c
+++ b/src/nvim/spellsuggest.c
@@ -509,7 +509,7 @@ void spell_suggest(int count)
// Get the word and its length.
// Figure out if the word should be capitalised.
- int need_cap = check_need_cap(curwin->w_cursor.lnum, curwin->w_cursor.col);
+ int need_cap = check_need_cap(curwin, curwin->w_cursor.lnum, curwin->w_cursor.col);
// Make a copy of current line since autocommands may free the line.
line = xstrdup(get_cursor_line_ptr());
diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c
index a6fd1d677b..015c578396 100644
--- a/src/nvim/statusline.c
+++ b/src/nvim/statusline.c
@@ -336,7 +336,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
grid_adjust(&grid, &row, &col);
if (row < 0) {
- return;
+ goto theend;
}
fillchar = wp->w_p_fcs_chars.wbr;
@@ -596,7 +596,7 @@ void win_redr_ruler(win_T *wp)
MAXSIZE_TEMP_ARRAY(content, 1);
MAXSIZE_TEMP_ARRAY(chunk, 2);
ADD_C(chunk, INTEGER_OBJ(attr));
- ADD_C(chunk, STRING_OBJ(cstr_as_string(buffer)));
+ ADD_C(chunk, CSTR_AS_OBJ(buffer));
ADD_C(content, ARRAY_OBJ(chunk));
ui_call_msg_ruler(content);
did_show_ext_ruler = true;
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index 5231ec0841..4e521b14f7 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -1502,7 +1502,8 @@ char *strrep(const char *src, const char *what, const char *rep)
return ret;
}
-static void byteidx(typval_T *argvars, typval_T *rettv, int comp)
+/// Implementation of "byteidx()" and "byteidxcomp()" functions
+static void byteidx_common(typval_T *argvars, typval_T *rettv, int comp)
{
rettv->vval.v_number = -1;
@@ -1514,7 +1515,11 @@ static void byteidx(typval_T *argvars, typval_T *rettv, int comp)
varnumber_T utf16idx = false;
if (argvars[2].v_type != VAR_UNKNOWN) {
- utf16idx = tv_get_bool(&argvars[2]);
+ bool error = false;
+ utf16idx = tv_get_bool_chk(&argvars[2], &error);
+ if (error) {
+ return;
+ }
if (utf16idx < 0 || utf16idx > 1) {
semsg(_(e_using_number_as_bool_nr), utf16idx);
return;
@@ -1550,13 +1555,13 @@ static void byteidx(typval_T *argvars, typval_T *rettv, int comp)
/// "byteidx()" function
void f_byteidx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- byteidx(argvars, rettv, false);
+ byteidx_common(argvars, rettv, false);
}
/// "byteidxcomp()" function
void f_byteidxcomp(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- byteidx(argvars, rettv, true);
+ byteidx_common(argvars, rettv, true);
}
/// "charidx()" function
@@ -1764,16 +1769,21 @@ void f_strcharlen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// "strchars()" function
void f_strchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- int skipcc = false;
+ varnumber_T skipcc = false;
if (argvars[1].v_type != VAR_UNKNOWN) {
- skipcc = (int)tv_get_bool(&argvars[1]);
- }
- if (skipcc < 0 || skipcc > 1) {
- semsg(_(e_using_number_as_bool_nr), skipcc);
- } else {
- strchar_common(argvars, rettv, skipcc);
+ bool error = false;
+ skipcc = tv_get_bool_chk(&argvars[1], &error);
+ if (error) {
+ return;
+ }
+ if (skipcc < 0 || skipcc > 1) {
+ semsg(_(e_using_number_as_bool_nr), skipcc);
+ return;
+ }
}
+
+ strchar_common(argvars, rettv, skipcc);
}
/// "strutf16len()" function
@@ -1840,7 +1850,10 @@ void f_strcharpart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (!error) {
if (argvars[2].v_type != VAR_UNKNOWN
&& argvars[3].v_type != VAR_UNKNOWN) {
- skipcc = tv_get_bool(&argvars[3]);
+ skipcc = tv_get_bool_chk(&argvars[3], &error);
+ if (error) {
+ return;
+ }
if (skipcc < 0 || skipcc > 1) {
semsg(_(e_using_number_as_bool_nr), skipcc);
return;
diff --git a/src/nvim/strings.h b/src/nvim/strings.h
index 6ad9daf5bf..f4ccf9b30c 100644
--- a/src/nvim/strings.h
+++ b/src/nvim/strings.h
@@ -6,7 +6,7 @@
#include <string.h>
#include "klib/kvec.h"
-#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/types.h"
/// Append string to string and return pointer to the next byte
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index ff16a10d8e..18331cc95d 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -732,7 +732,7 @@ void do_tag(char *tag, int type, int count, int forceit, int verbose)
num_matches,
max_num_matches != MAXCOL ? _(" or more") : "");
if (ic) {
- STRCAT(IObuff, _(" Using tag with different case!"));
+ xstrlcat(IObuff, _(" Using tag with different case!"), IOSIZE);
}
if ((num_matches > prev_num_matches || new_tag)
&& num_matches > 1) {
@@ -2901,21 +2901,10 @@ static int jumpto_tag(const char *lbuf_arg, int forceit, int keep_help)
buf_T *const existing_buf = buflist_findname_exp(fname);
if (existing_buf != NULL) {
- const win_T *wp = NULL;
-
- if (swb_flags & SWB_USEOPEN) {
- wp = buf_jump_open_win(existing_buf);
- }
-
- // If 'switchbuf' contains "usetab": jump to first window in any tab
- // page containing "existing_buf" if one exists
- if (wp == NULL && (swb_flags & SWB_USETAB)) {
- wp = buf_jump_open_tab(existing_buf);
- }
-
- // We've switched to the buffer, the usual loading of the file must
- // be skipped.
- if (wp != NULL) {
+ // If 'switchbuf' is set jump to the window containing "buf".
+ if (swbuf_goto_win_with_buf(existing_buf) != NULL) {
+ // We've switched to the buffer, the usual loading of the file
+ // must be skipped.
getfile_result = GETFILE_SAME_FILE;
}
}
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 0686305d02..792071963d 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -169,7 +169,7 @@ static VTermScreenCallbacks vterm_screen_callbacks = {
.sb_popline = term_sb_pop,
};
-static PMap(ptr_t) invalidated_terminals = MAP_INIT;
+static Set(ptr_t) invalidated_terminals = SET_INIT;
void terminal_init(void)
{
@@ -183,10 +183,10 @@ void terminal_teardown(void)
time_watcher_stop(&refresh_timer);
multiqueue_free(refresh_timer.events);
time_watcher_close(&refresh_timer, NULL);
- pmap_destroy(ptr_t)(&invalidated_terminals);
+ set_destroy(ptr_t, &invalidated_terminals);
// terminal_destroy might be called after terminal_teardown is invoked
// make sure it is in an empty, valid state
- pmap_init(ptr_t, &invalidated_terminals);
+ invalidated_terminals = (Set(ptr_t)) SET_INIT;
}
static void term_output_callback(const char *s, size_t len, void *user_data)
@@ -220,6 +220,7 @@ Terminal *terminal_open(buf_T *buf, TerminalOptions opts)
// Set up screen
rv->vts = vterm_obtain_screen(rv->vt);
vterm_screen_enable_altscreen(rv->vts, true);
+ vterm_screen_enable_reflow(rv->vts, true);
// delete empty lines at the end of the buffer
vterm_screen_set_callbacks(rv->vts, &vterm_screen_callbacks, rv);
vterm_screen_set_damage_merge(rv->vts, VTERM_DAMAGE_SCROLL);
@@ -596,7 +597,7 @@ static int terminal_execute(VimState *state, int key)
break;
case K_LUA:
- map_execute_lua();
+ map_execute_lua(false);
break;
case Ctrl_N:
@@ -652,12 +653,12 @@ void terminal_destroy(Terminal **termpp)
}
if (!term->refcount) {
- if (pmap_has(ptr_t)(&invalidated_terminals, term)) {
+ if (set_has(ptr_t, &invalidated_terminals, term)) {
// flush any pending changes to the buffer
block_autocmds();
refresh_terminal(term);
unblock_autocmds();
- pmap_del(ptr_t)(&invalidated_terminals, term);
+ set_del(ptr_t, &invalidated_terminals, term);
}
for (size_t i = 0; i < term->sb_current; i++) {
xfree(term->sb_buffer[i]);
@@ -1027,7 +1028,7 @@ static int term_sb_push(int cols, const VTermScreenCell *cells, void *data)
}
memcpy(sbrow->cells, cells, sizeof(cells[0]) * c);
- pmap_put(ptr_t)(&invalidated_terminals, term, NULL);
+ set_put(ptr_t, &invalidated_terminals, term);
return 1;
}
@@ -1068,7 +1069,7 @@ static int term_sb_pop(int cols, VTermScreenCell *cells, void *data)
}
xfree(sbrow);
- pmap_put(ptr_t)(&invalidated_terminals, term, NULL);
+ set_put(ptr_t, &invalidated_terminals, term);
return 1;
}
@@ -1524,7 +1525,7 @@ static void invalidate_terminal(Terminal *term, int start_row, int end_row)
term->invalid_end = MAX(term->invalid_end, end_row);
}
- pmap_put(ptr_t)(&invalidated_terminals, term, NULL);
+ set_put(ptr_t, &invalidated_terminals, term);
if (!refresh_pending) {
time_watcher_start(&refresh_timer, refresh_timer_cb, REFRESH_DELAY, 0);
refresh_pending = true;
@@ -1567,10 +1568,10 @@ static void refresh_timer_cb(TimeWatcher *watcher, void *data)
void *stub; (void)(stub);
// don't process autocommands while updating terminal buffers
block_autocmds();
- map_foreach(&invalidated_terminals, term, stub, {
+ set_foreach(&invalidated_terminals, term, {
refresh_terminal(term);
});
- pmap_clear(ptr_t)(&invalidated_terminals);
+ set_clear(ptr_t, &invalidated_terminals);
unblock_autocmds();
}
diff --git a/src/nvim/testing.c b/src/nvim/testing.c
index 5483a58525..25ec8e898a 100644
--- a/src/nvim/testing.c
+++ b/src/nvim/testing.c
@@ -418,11 +418,11 @@ static int assert_equalfile(typval_T *argvars)
const int c2 = fgetc(fd2);
if (c1 == EOF) {
if (c2 != EOF) {
- STRCPY(IObuff, "first file is shorter");
+ xstrlcpy(IObuff, "first file is shorter", IOSIZE);
}
break;
} else if (c2 == EOF) {
- STRCPY(IObuff, "second file is shorter");
+ xstrlcpy(IObuff, "second file is shorter", IOSIZE);
break;
} else {
line1[lineidx] = (char)c1;
diff --git a/src/nvim/testing.h b/src/nvim/testing.h
index 69596d725c..69ceeb16b5 100644
--- a/src/nvim/testing.h
+++ b/src/nvim/testing.h
@@ -1,7 +1,7 @@
#ifndef NVIM_TESTING_H
#define NVIM_TESTING_H
-#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "testing.h.generated.h"
diff --git a/src/nvim/textobject.c b/src/nvim/textobject.c
index 428b14a68d..5036c10827 100644
--- a/src/nvim/textobject.c
+++ b/src/nvim/textobject.c
@@ -22,6 +22,7 @@
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/move.h"
#include "nvim/normal.h"
#include "nvim/option_defs.h"
#include "nvim/pos.h"
@@ -414,6 +415,7 @@ int bck_word(long count, bool bigword, bool stop)
finished:
stop = false;
}
+ adjust_skipcol();
return OK;
}
@@ -518,6 +520,7 @@ int bckend_word(long count, bool bigword, bool eol)
}
}
}
+ adjust_skipcol();
return OK;
}
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 73ed7b6096..30a1af68ad 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -33,7 +33,7 @@
#define KEY_BUFFER_SIZE 0xfff
static const struct kitty_key_map_entry {
- KittyKey key;
+ int key;
const char *name;
} kitty_key_map_entry[] = {
{ KITTY_KEY_ESCAPE, "Esc" },
@@ -115,7 +115,7 @@ static const struct kitty_key_map_entry {
{ KITTY_KEY_KP_BEGIN, "kOrigin" },
};
-static Map(KittyKey, cstr_t) kitty_key_map = MAP_INIT;
+static Map(int, cstr_t) kitty_key_map = MAP_INIT;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "tui/input.c.generated.h"
@@ -135,8 +135,8 @@ void tinput_init(TermInput *input, Loop *loop)
input->key_buffer = rbuffer_new(KEY_BUFFER_SIZE);
for (size_t i = 0; i < ARRAY_SIZE(kitty_key_map_entry); i++) {
- map_put(KittyKey, cstr_t)(&kitty_key_map, kitty_key_map_entry[i].key,
- kitty_key_map_entry[i].name);
+ map_put(int, cstr_t)(&kitty_key_map, kitty_key_map_entry[i].key,
+ kitty_key_map_entry[i].name);
}
input->in_fd = STDIN_FILENO;
@@ -162,7 +162,7 @@ void tinput_init(TermInput *input, Loop *loop)
void tinput_destroy(TermInput *input)
{
- map_destroy(KittyKey, cstr_t)(&kitty_key_map);
+ map_destroy(int, &kitty_key_map);
rbuffer_free(input->key_buffer);
time_watcher_close(&input->timer_handle, NULL);
stream_close(&input->read_stream, NULL, NULL);
@@ -231,7 +231,7 @@ static void tinput_enqueue(TermInput *input, char *buf, size_t size)
static void handle_kitty_key_protocol(TermInput *input, TermKeyKey *key)
{
- const char *name = map_get(KittyKey, cstr_t)(&kitty_key_map, (KittyKey)key->code.codepoint);
+ const char *name = map_get(int, cstr_t)(&kitty_key_map, (int)key->code.codepoint);
if (name) {
char buf[64];
size_t len = 0;
@@ -257,7 +257,7 @@ static void forward_simple_utf8(TermInput *input, TermKeyKey *key)
char *ptr = key->utf8;
if (key->code.codepoint >= 0xE000 && key->code.codepoint <= 0xF8FF
- && map_has(KittyKey, cstr_t)(&kitty_key_map, (KittyKey)key->code.codepoint)) {
+ && map_has(int, cstr_t)(&kitty_key_map, (int)key->code.codepoint)) {
handle_kitty_key_protocol(input, key);
return;
}
@@ -286,8 +286,7 @@ static void forward_modified_utf8(TermInput *input, TermKeyKey *key)
} else {
assert(key->modifiers);
if (key->code.codepoint >= 0xE000 && key->code.codepoint <= 0xF8FF
- && map_has(KittyKey, cstr_t)(&kitty_key_map,
- (KittyKey)key->code.codepoint)) {
+ && map_has(int, cstr_t)(&kitty_key_map, (int)key->code.codepoint)) {
handle_kitty_key_protocol(input, key);
return;
}
@@ -548,8 +547,8 @@ static void set_bg(char *bgvalue)
{
if (ui_client_attached) {
MAXSIZE_TEMP_ARRAY(args, 2);
- ADD_C(args, STRING_OBJ(cstr_as_string("term_background")));
- ADD_C(args, STRING_OBJ(cstr_as_string(bgvalue)));
+ ADD_C(args, CSTR_AS_OBJ("term_background"));
+ ADD_C(args, CSTR_AS_OBJ(bgvalue));
rpc_send_event(ui_client_channel_id, "nvim_ui_set_option", args);
}
}
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 2de1467511..c9d9b08b79 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -106,6 +106,7 @@ struct TUIData {
bool bce;
bool mouse_enabled;
bool mouse_move_enabled;
+ bool title_enabled;
bool busy, is_invisible, want_invisible;
bool cork, overflow;
bool set_cursor_color_as_str;
@@ -325,8 +326,6 @@ static void terminfo_start(TUIData *tui)
// Enter alternate screen, save title, and clear.
// NOTE: Do this *before* changing terminal settings. #6433
unibi_out(tui, unibi_enter_ca_mode);
- // Save title/icon to the "stack". #4063
- unibi_out_ext(tui, tui->unibi_ext.save_title);
unibi_out(tui, unibi_keypad_xmit);
unibi_out(tui, unibi_clear_screen);
// Ask the terminal to send us the background color.
@@ -383,8 +382,7 @@ static void terminfo_stop(TUIData *tui)
// Disable extended keys before exiting alternate screen.
unibi_out_ext(tui, tui->unibi_ext.disable_extended_keys);
unibi_out(tui, unibi_exit_ca_mode);
- // Restore title/icon from the "stack". #4063
- unibi_out_ext(tui, tui->unibi_ext.restore_title);
+ tui_set_title(tui, (String)STRING_INIT);
if (tui->cursor_color_changed) {
unibi_out_ext(tui, tui->unibi_ext.reset_cursor_color);
}
@@ -1304,16 +1302,16 @@ static void show_verbose_terminfo(TUIData *tui)
Array chunks = ARRAY_DICT_INIT;
Array title = ARRAY_DICT_INIT;
- ADD(title, STRING_OBJ(cstr_to_string("\n\n--- Terminal info --- {{{\n")));
- ADD(title, STRING_OBJ(cstr_to_string("Title")));
+ ADD(title, CSTR_TO_OBJ("\n\n--- Terminal info --- {{{\n"));
+ ADD(title, CSTR_TO_OBJ("Title"));
ADD(chunks, ARRAY_OBJ(title));
Array info = ARRAY_DICT_INIT;
String str = terminfo_info_msg(ut, tui->term);
ADD(info, STRING_OBJ(str));
ADD(chunks, ARRAY_OBJ(info));
Array end_fold = ARRAY_DICT_INIT;
- ADD(end_fold, STRING_OBJ(cstr_to_string("}}}\n")));
- ADD(end_fold, STRING_OBJ(cstr_to_string("Title")));
+ ADD(end_fold, CSTR_TO_OBJ("}}}\n"));
+ ADD(end_fold, CSTR_TO_OBJ("Title"));
ADD(chunks, ARRAY_OBJ(end_fold));
Array args = ARRAY_DICT_INIT;
@@ -1361,13 +1359,24 @@ void tui_suspend(TUIData *tui)
void tui_set_title(TUIData *tui, String title)
{
- if (!(title.data && unibi_get_str(tui->ut, unibi_to_status_line)
+ if (!(unibi_get_str(tui->ut, unibi_to_status_line)
&& unibi_get_str(tui->ut, unibi_from_status_line))) {
return;
}
- unibi_out(tui, unibi_to_status_line);
- out(tui, title.data, title.size);
- unibi_out(tui, unibi_from_status_line);
+ if (title.size > 0) {
+ if (!tui->title_enabled) {
+ // Save title/icon to the "stack". #4063
+ unibi_out_ext(tui, tui->unibi_ext.save_title);
+ tui->title_enabled = true;
+ }
+ unibi_out(tui, unibi_to_status_line);
+ out(tui, title.data, title.size);
+ unibi_out(tui, unibi_from_status_line);
+ } else if (tui->title_enabled) {
+ // Restore title/icon from the "stack". #4063
+ unibi_out_ext(tui, tui->unibi_ext.restore_title);
+ tui->title_enabled = false;
+ }
}
void tui_set_icon(TUIData *tui, String icon)
@@ -1416,7 +1425,7 @@ void tui_option_set(TUIData *tui, String name, Object value)
if (ui_client_channel_id) {
MAXSIZE_TEMP_ARRAY(args, 2);
- ADD_C(args, STRING_OBJ(cstr_as_string("rgb")));
+ ADD_C(args, CSTR_AS_OBJ("rgb"));
ADD_C(args, BOOLEAN_OBJ(value.data.boolean));
rpc_send_event(ui_client_channel_id, "nvim_ui_set_option", args);
}
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 6d09b9f3a3..8c31032492 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -127,10 +127,10 @@ void ui_free_all_mem(void)
kv_destroy(call_buf);
UIEventCallback *event_cb;
- map_foreach_value(&ui_event_cbs, event_cb, {
+ pmap_foreach_value(&ui_event_cbs, event_cb, {
free_ui_event_callback(event_cb);
})
- pmap_destroy(uint32_t)(&ui_event_cbs);
+ map_destroy(uint32_t, &ui_event_cbs);
}
#endif
@@ -613,8 +613,8 @@ Array ui_array(void)
PUT(info, "override", BOOLEAN_OBJ(ui->override));
// TUI fields. (`stdin_fd` is intentionally omitted.)
- PUT(info, "term_name", STRING_OBJ(cstr_to_string(ui->term_name)));
- PUT(info, "term_background", STRING_OBJ(cstr_to_string(ui->term_background)));
+ PUT(info, "term_name", CSTR_TO_OBJ(ui->term_name));
+ PUT(info, "term_background", CSTR_TO_OBJ(ui->term_background));
PUT(info, "term_colors", INTEGER_OBJ(ui->term_colors));
PUT(info, "stdin_tty", BOOLEAN_OBJ(ui->stdin_tty));
PUT(info, "stdout_tty", BOOLEAN_OBJ(ui->stdout_tty));
@@ -660,7 +660,7 @@ void ui_call_event(char *name, Array args)
{
UIEventCallback *event_cb;
bool handled = false;
- map_foreach_value(&ui_event_cbs, event_cb, {
+ pmap_foreach_value(&ui_event_cbs, event_cb, {
Error err = ERROR_INIT;
Object res = nlua_call_ref(event_cb->cb, name, args, false, &err);
if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
@@ -686,7 +686,7 @@ void ui_cb_update_ext(void)
for (size_t i = 0; i < kUIGlobalCount; i++) {
UIEventCallback *event_cb;
- map_foreach_value(&ui_event_cbs, event_cb, {
+ pmap_foreach_value(&ui_event_cbs, event_cb, {
if (event_cb->ext_widgets[i]) {
ui_cb_ext[i] = true;
break;
@@ -710,9 +710,9 @@ void ui_add_cb(uint32_t ns_id, LuaRef cb, bool *ext_widgets)
event_cb->ext_widgets[kUICmdline] = true;
}
- UIEventCallback **item = (UIEventCallback **)pmap_ref(uint32_t)(&ui_event_cbs, ns_id, true);
+ ptr_t *item = pmap_put_ref(uint32_t)(&ui_event_cbs, ns_id, NULL, NULL);
if (*item) {
- free_ui_event_callback(*item);
+ free_ui_event_callback((UIEventCallback *)(*item));
}
*item = event_cb;
@@ -723,8 +723,8 @@ void ui_add_cb(uint32_t ns_id, LuaRef cb, bool *ext_widgets)
void ui_remove_cb(uint32_t ns_id)
{
if (pmap_has(uint32_t)(&ui_event_cbs, ns_id)) {
- free_ui_event_callback(pmap_get(uint32_t)(&ui_event_cbs, ns_id));
- pmap_del(uint32_t)(&ui_event_cbs, ns_id);
+ UIEventCallback *item = pmap_del(uint32_t)(&ui_event_cbs, ns_id, NULL);
+ free_ui_event_callback(item);
}
ui_cb_update_ext();
ui_refresh();
diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c
index b93b31f7dc..1918b0b800 100644
--- a/src/nvim/ui_client.c
+++ b/src/nvim/ui_client.c
@@ -83,11 +83,11 @@ void ui_client_attach(int width, int height, char *term)
PUT_C(opts, "ext_linegrid", BOOLEAN_OBJ(true));
PUT_C(opts, "ext_termcolors", BOOLEAN_OBJ(true));
if (term) {
- PUT_C(opts, "term_name", STRING_OBJ(cstr_as_string(term)));
+ PUT_C(opts, "term_name", CSTR_AS_OBJ(term));
}
if (ui_client_bg_response != kNone) {
bool is_dark = (ui_client_bg_response == kTrue);
- PUT_C(opts, "term_background", STRING_OBJ(cstr_as_string(is_dark ? "dark" : "light")));
+ PUT_C(opts, "term_background", CSTR_AS_OBJ(is_dark ? "dark" : "light"));
}
PUT_C(opts, "term_colors", INTEGER_OBJ(t_colors));
if (!ui_client_is_remote) {
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 35f46e512d..1eb73d85d7 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -120,6 +120,7 @@
#include "nvim/path.h"
#include "nvim/pos.h"
#include "nvim/sha256.h"
+#include "nvim/spell.h"
#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/types.h"
@@ -2372,6 +2373,12 @@ static void u_undoredo(int undo, bool do_buf_event)
}
changed_lines(top + 1, 0, bot, newsize - oldsize, do_buf_event);
+ // When text has been changed, possibly the start of the next line
+ // may have SpellCap that should be removed or it needs to be
+ // displayed. Schedule the next line for redrawing just in case.
+ if (spell_check_window(curwin) && bot <= curbuf->b_ml.ml_line_count) {
+ redrawWinline(curwin, bot);
+ }
// Set the '[ mark.
if (top + 1 < curbuf->b_op_start.lnum) {
@@ -2667,7 +2674,7 @@ void ex_undolist(exarg_T *eap)
undo_fmt_time(IObuff + strlen(IObuff), IOSIZE - strlen(IObuff), uhp->uh_time);
if (uhp->uh_save_nr > 0) {
while (strlen(IObuff) < 33) {
- STRCAT(IObuff, " ");
+ xstrlcat(IObuff, " ", IOSIZE);
}
vim_snprintf_add(IObuff, IOSIZE, " %3ld", uhp->uh_save_nr);
}
diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c
index 11f2620aaa..c56b241988 100644
--- a/src/nvim/usercmd.c
+++ b/src/nvim/usercmd.c
@@ -1754,8 +1754,8 @@ Dictionary commands_array(buf_T *buf)
Dictionary d = ARRAY_DICT_INIT;
ucmd_T *cmd = USER_CMD_GA(gap, i);
- PUT(d, "name", STRING_OBJ(cstr_to_string(cmd->uc_name)));
- PUT(d, "definition", STRING_OBJ(cstr_to_string(cmd->uc_rep)));
+ PUT(d, "name", CSTR_TO_OBJ(cmd->uc_name));
+ PUT(d, "definition", CSTR_TO_OBJ(cmd->uc_rep));
PUT(d, "script_id", INTEGER_OBJ(cmd->uc_script_ctx.sc_sid));
PUT(d, "bang", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_BANG)));
PUT(d, "bar", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_TRLBAR)));
@@ -1775,21 +1775,21 @@ Dictionary commands_array(buf_T *buf)
case (EX_EXTRA | EX_NOSPC | EX_NEEDARG):
arg[0] = '1'; break;
}
- PUT(d, "nargs", STRING_OBJ(cstr_to_string(arg)));
+ PUT(d, "nargs", CSTR_TO_OBJ(arg));
char *cmd_compl = get_command_complete(cmd->uc_compl);
PUT(d, "complete", (cmd_compl == NULL
- ? NIL : STRING_OBJ(cstr_to_string(cmd_compl))));
+ ? NIL : CSTR_TO_OBJ(cmd_compl)));
PUT(d, "complete_arg", cmd->uc_compl_arg == NULL
- ? NIL : STRING_OBJ(cstr_to_string(cmd->uc_compl_arg)));
+ ? NIL : CSTR_TO_OBJ(cmd->uc_compl_arg));
Object obj = NIL;
if (cmd->uc_argt & EX_COUNT) {
if (cmd->uc_def >= 0) {
snprintf(str, sizeof(str), "%" PRId64, cmd->uc_def);
- obj = STRING_OBJ(cstr_to_string(str)); // -count=N
+ obj = CSTR_TO_OBJ(str); // -count=N
} else {
- obj = STRING_OBJ(cstr_to_string("0")); // -count
+ obj = CSTR_TO_OBJ("0"); // -count
}
}
PUT(d, "count", obj);
@@ -1797,12 +1797,12 @@ Dictionary commands_array(buf_T *buf)
obj = NIL;
if (cmd->uc_argt & EX_RANGE) {
if (cmd->uc_argt & EX_DFLALL) {
- obj = STRING_OBJ(cstr_to_string("%")); // -range=%
+ obj = CSTR_TO_OBJ("%"); // -range=%
} else if (cmd->uc_def >= 0) {
snprintf(str, sizeof(str), "%" PRId64, cmd->uc_def);
- obj = STRING_OBJ(cstr_to_string(str)); // -range=N
+ obj = CSTR_TO_OBJ(str); // -range=N
} else {
- obj = STRING_OBJ(cstr_to_string(".")); // -range
+ obj = CSTR_TO_OBJ("."); // -range
}
}
PUT(d, "range", obj);
@@ -1811,7 +1811,7 @@ Dictionary commands_array(buf_T *buf)
for (int j = 0; addr_type_complete[j].expand != ADDR_NONE; j++) {
if (addr_type_complete[j].expand != ADDR_LINES
&& addr_type_complete[j].expand == cmd->uc_addr_type) {
- obj = STRING_OBJ(cstr_to_string(addr_type_complete[j].name));
+ obj = CSTR_TO_OBJ(addr_type_complete[j].name);
break;
}
}
diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c
index d1c6426cba..830d8c5f34 100644
--- a/src/nvim/viml/parser/expressions.c
+++ b/src/nvim/viml/parser/expressions.c
@@ -2866,7 +2866,7 @@ viml_pexpr_parse_no_paren_closing_error: {}
case kENodeOperator:
if (prev_token.type == kExprLexSpacing) {
// For some reason "function (args)" is a function call, but
- // "(funcref) (args)" is not. AFAIR this somehow involves
+ // "(funcref) (args)" is not. As far as I remember this somehow involves
// compatibility and Bram was commenting that this is
// intentionally inconsistent and he is not very happy with the
// situation himself.
diff --git a/src/nvim/viml/parser/expressions.h b/src/nvim/viml/parser/expressions.h
index 6fe6a784a0..245f4c500c 100644
--- a/src/nvim/viml/parser/expressions.h
+++ b/src/nvim/viml/parser/expressions.h
@@ -5,7 +5,6 @@
#include <stddef.h>
#include <stdint.h>
-#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/types.h"
#include "nvim/viml/parser/parser.h"
diff --git a/src/nvim/window.c b/src/nvim/window.c
index fd6755a382..90c8ba92f9 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -139,6 +139,32 @@ win_T *prevwin_curwin(void)
return is_in_cmdwin() && prevwin != NULL ? prevwin : curwin;
}
+/// If the 'switchbuf' option contains "useopen" or "usetab", then try to jump
+/// to a window containing "buf".
+/// Returns the pointer to the window that was jumped to or NULL.
+win_T *swbuf_goto_win_with_buf(buf_T *buf)
+{
+ win_T *wp = NULL;
+
+ if (buf == NULL) {
+ return wp;
+ }
+
+ // If 'switchbuf' contains "useopen": jump to first window in the current
+ // tab page containing "buf" if one exists.
+ if (swb_flags & SWB_USEOPEN) {
+ wp = buf_jump_open_win(buf);
+ }
+
+ // If 'switchbuf' contains "usetab": jump to first window in any tab page
+ // containing "buf" if one exists.
+ if (wp == NULL && (swb_flags & SWB_USETAB)) {
+ wp = buf_jump_open_tab(buf);
+ }
+
+ return wp;
+}
+
/// all CTRL-W window commands are handled here, called from normal_cmd().
///
/// @param xchar extra char from ":wincmd gx" or NUL
@@ -514,18 +540,31 @@ wingotofile:
tabpage_T *oldtab = curtab;
win_T *oldwin = curwin;
setpcmark();
- if (win_split(0, 0) == OK) {
+
+ // If 'switchbuf' is set to 'useopen' or 'usetab' and the
+ // file is already opened in a window, then jump to it.
+ win_T *wp = NULL;
+ if ((swb_flags & (SWB_USEOPEN | SWB_USETAB))
+ && cmdmod.cmod_tab == 0) {
+ wp = swbuf_goto_win_with_buf(buflist_findname_exp(ptr));
+ }
+
+ if (wp == NULL && win_split(0, 0) == OK) {
RESET_BINDING(curwin);
if (do_ecmd(0, ptr, NULL, NULL, ECMD_LASTL, ECMD_HIDE, NULL) == FAIL) {
// Failed to open the file, close the window opened for it.
win_close(curwin, false, false);
goto_tabpage_win(oldtab, oldwin);
- } else if (nchar == 'F' && lnum >= 0) {
- curwin->w_cursor.lnum = lnum;
- check_cursor_lnum();
- beginline(BL_SOL | BL_FIX);
+ } else {
+ wp = curwin;
}
}
+
+ if (wp != NULL && nchar == 'F' && lnum >= 0) {
+ curwin->w_cursor.lnum = lnum;
+ check_cursor_lnum();
+ beginline(BL_SOL | BL_FIX);
+ }
xfree(ptr);
}
break;
@@ -2278,6 +2317,9 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
}
if (hnc) { // add next_curwin size
next_curwin_size -= (int)p_wiw - (m - n);
+ if (next_curwin_size < 0) {
+ next_curwin_size = 0;
+ }
new_size += next_curwin_size;
room -= new_size - next_curwin_size;
} else {
@@ -4035,7 +4077,7 @@ static tabpage_T *alloc_tabpage(void)
static int last_tp_handle = 0;
tabpage_T *tp = xcalloc(1, sizeof(tabpage_T));
tp->handle = ++last_tp_handle;
- pmap_put(handle_T)(&tabpage_handles, tp->handle, tp);
+ pmap_put(int)(&tabpage_handles, tp->handle, tp);
// Init t: variables.
tp->tp_vars = tv_dict_alloc();
@@ -4048,7 +4090,7 @@ static tabpage_T *alloc_tabpage(void)
void free_tabpage(tabpage_T *tp)
{
- pmap_del(handle_T)(&tabpage_handles, tp->handle);
+ pmap_del(int)(&tabpage_handles, tp->handle, NULL);
diff_clear(tp);
for (int idx = 0; idx < SNAP_COUNT; idx++) {
clear_snapshot(tp, idx);
@@ -5020,7 +5062,7 @@ static win_T *win_alloc(win_T *after, bool hidden)
win_T *new_wp = xcalloc(1, sizeof(win_T));
new_wp->handle = ++last_win_id;
- pmap_put(handle_T)(&window_handles, new_wp->handle, new_wp);
+ pmap_put(int)(&window_handles, new_wp->handle, new_wp);
grid_assign_handle(&new_wp->w_grid_alloc);
@@ -5082,7 +5124,7 @@ void free_wininfo(wininfo_T *wip, buf_T *bp)
/// @param tp tab page "win" is in, NULL for current
static void win_free(win_T *wp, tabpage_T *tp)
{
- pmap_del(handle_T)(&window_handles, wp->handle);
+ pmap_del(int)(&window_handles, wp->handle, NULL);
clearFolding(wp);
// reduce the reference count to the argument list.
@@ -6660,7 +6702,8 @@ static int win_border_width(win_T *wp)
/// Set the width of a window.
void win_new_width(win_T *wp, int width)
{
- wp->w_width = width;
+ // Should we give an error if width < 0?
+ wp->w_width = width < 0 ? 0 : width;
wp->w_pos_changed = true;
win_set_inner_size(wp, true);
}
diff --git a/src/nvim/window.h b/src/nvim/window.h
index 4ab2bea60a..9201800d53 100644
--- a/src/nvim/window.h
+++ b/src/nvim/window.h
@@ -4,13 +4,9 @@
#include <stdbool.h>
#include <stddef.h>
-#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/macros.h"
-#include "nvim/mark.h"
-#include "nvim/os/os.h"
-#include "nvim/os/os_defs.h"
-#include "nvim/vim.h"
+#include "nvim/option_defs.h"
// Values for file_name_in_line()
#define FNAME_MESS 1 // give error message
diff --git a/src/uncrustify.cfg b/src/uncrustify.cfg
index 5934c088df..32cf173741 100644
--- a/src/uncrustify.cfg
+++ b/src/uncrustify.cfg
@@ -1,4 +1,4 @@
-# Uncrustify-0.76.0_f
+# Uncrustify-0.77.1_f
#
# General options
@@ -195,6 +195,11 @@ sp_before_ptr_star = force # ignore/add/remove/force/not_defined
# variable name. If set to ignore, sp_before_ptr_star is used instead.
sp_before_unnamed_ptr_star = ignore # ignore/add/remove/force/not_defined
+# Add or remove space between a qualifier and a pointer star '*' that isn't
+# followed by a variable name, as in '(char const *)'. If set to ignore,
+# sp_before_ptr_star is used instead.
+sp_qualifier_unnamed_ptr_star = ignore # ignore/add/remove/force/not_defined
+
# Add or remove space between pointer stars '*', as in 'int ***a;'.
sp_between_ptr_star = ignore # ignore/add/remove/force/not_defined
@@ -232,13 +237,24 @@ sp_ptr_star_func_type = ignore # ignore/add/remove/force/not_defined
sp_ptr_star_paren = ignore # ignore/add/remove/force/not_defined
# Add or remove space before a pointer star '*', if followed by a function
-# prototype or function definition.
+# prototype or function definition. If set to ignore, sp_before_ptr_star is
+# used instead.
sp_before_ptr_star_func = ignore # ignore/add/remove/force/not_defined
+# Add or remove space between a qualifier and a pointer star '*' followed by
+# the name of the function in a function prototype or definition, as in
+# 'char const *foo()`. If set to ignore, sp_before_ptr_star is used instead.
+sp_qualifier_ptr_star_func = ignore # ignore/add/remove/force/not_defined
+
# Add or remove space before a pointer star '*' in the trailing return of a
# function prototype or function definition.
sp_before_ptr_star_trailing = ignore # ignore/add/remove/force/not_defined
+# Add or remove space between a qualifier and a pointer star '*' in the
+# trailing return of a function prototype or function definition, as in
+# 'auto foo() -> char const *'.
+sp_qualifier_ptr_star_trailing = ignore # ignore/add/remove/force/not_defined
+
# Add or remove space before a reference sign '&'.
sp_before_byref = ignore # ignore/add/remove/force/not_defined
@@ -628,6 +644,16 @@ sp_inside_fparens = remove # ignore/add/remove/force/not_defined
# Add or remove space inside function '(' and ')'.
sp_inside_fparen = remove # ignore/add/remove/force/not_defined
+# Add or remove space inside user functor '(' and ')'.
+sp_func_call_user_inside_rparen = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove space inside empty functor '()'.
+# Overrides sp_after_angle unless use_sp_after_angle_always is set to true.
+sp_inside_rparens = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove space inside functor '(' and ')'.
+sp_inside_rparen = ignore # ignore/add/remove/force/not_defined
+
# Add or remove space inside the first parentheses in a function type, as in
# 'void (*x)(...)'.
sp_inside_tparen = remove # ignore/add/remove/force/not_defined
@@ -967,6 +993,14 @@ sp_extern_paren = ignore # ignore/add/remove/force/not_defined
# Add or remove space after the opening of a C++ comment, as in '// <here> A'.
sp_cmt_cpp_start = ignore # ignore/add/remove/force/not_defined
+# remove space after the '//' and the pvs command '-V1234',
+# only works with sp_cmt_cpp_start set to add or force.
+sp_cmt_cpp_pvs = false # true/false
+
+# remove space after the '//' and the command 'lint',
+# only works with sp_cmt_cpp_start set to add or force.
+sp_cmt_cpp_lint = false # true/false
+
# Add or remove space in a C++ region marker comment, as in '// <here> BEGIN'.
# A region marker is defined as a comment which is not preceded by other text
# (i.e. the comment is the first non-whitespace on the line), and which starts
@@ -2833,9 +2867,16 @@ align_single_line_brace_gap = 0 # unsigned number
# 0: Don't align (default).
align_oc_msg_spec_span = 0 # unsigned number
-# Whether to align macros wrapped with a backslash and a newline. This will
-# not work right if the macro contains a multi-line comment.
-align_nl_cont = false # true/false
+# Whether and how to align backslashes that split a macro onto multiple lines.
+# This will not work right if the macro contains a multi-line comment.
+#
+# 0: Do nothing (default)
+# 1: Align the backslashes in the column at the end of the longest line
+# 2: Align with the backslash that is farthest to the left, or, if that
+# backslash is farther left than the end of the longest line, at the end of
+# the longest line
+# 3: Align with the backslash that is farthest to the right
+align_nl_cont = 0 # unsigned number
# Whether to align macro functions and variables together.
align_pp_define_together = false # true/false
@@ -3146,6 +3187,12 @@ mod_remove_extra_semicolon = true # true/false
# Whether to remove duplicate include.
mod_remove_duplicate_include = true # true/false
+# the following options (mod_XX_closebrace_comment) use different comment,
+# depending of the setting of the next option.
+# false: Use the c comment (default)
+# true : Use the cpp comment
+mod_add_force_c_closebrace_comment = false # true/false
+
# If a function body exceeds the specified number of newlines and doesn't have
# a comment after the close brace, a comment will be added.
mod_add_long_function_closebrace_comment = 0 # unsigned number
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 38d881dbbc..77fe7b3b82 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -20,12 +20,14 @@ if(LUA_HAS_FFI)
-D BUSTED_OUTPUT_TYPE=${BUSTED_OUTPUT_TYPE}
-D TEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}
-D BUILD_DIR=${CMAKE_BINARY_DIR}
+ -D DEPS_INSTALL_DIR=${DEPS_INSTALL_DIR}
-D TEST_TYPE=unit
-D CIRRUS_CI=$ENV{CIRRUS_CI}
-D CI_BUILD=${CI_BUILD}
-P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
DEPENDS ${UNITTEST_PREREQS}
USES_TERMINAL)
+ add_dependencies(unittest test_deps)
else()
message(WARNING "disabling unit tests: no Luajit FFI in ${LUA_PRG}")
endif()
@@ -41,7 +43,7 @@ add_custom_target(functionaltest
-D BUSTED_OUTPUT_TYPE=${BUSTED_OUTPUT_TYPE}
-D TEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}
-D BUILD_DIR=${CMAKE_BINARY_DIR}
- -D DEPS_PREFIX=${DEPS_PREFIX}
+ -D DEPS_INSTALL_DIR=${DEPS_INSTALL_DIR}
-D TEST_TYPE=functional
-D CIRRUS_CI=$ENV{CIRRUS_CI}
-D CI_BUILD=${CI_BUILD}
@@ -56,6 +58,7 @@ add_custom_target(benchmark
-D BUSTED_OUTPUT_TYPE=${BUSTED_OUTPUT_TYPE}
-D TEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}
-D BUILD_DIR=${CMAKE_BINARY_DIR}
+ -D DEPS_INSTALL_DIR=${DEPS_INSTALL_DIR}
-D TEST_TYPE=benchmark
-D CIRRUS_CI=$ENV{CIRRUS_CI}
-D CI_BUILD=${CI_BUILD}
@@ -63,16 +66,5 @@ add_custom_target(benchmark
DEPENDS ${BENCHMARK_PREREQS}
USES_TERMINAL)
-add_custom_target(functionaltest-lua
- COMMAND ${CMAKE_COMMAND}
- -D NVIM_PRG=$<TARGET_FILE:nvim>
- -D WORKING_DIR=${PROJECT_SOURCE_DIR}
- -D BUSTED_OUTPUT_TYPE=${BUSTED_OUTPUT_TYPE}
- -D TEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}
- -D BUILD_DIR=${CMAKE_BINARY_DIR}
- -D TEST_TYPE=functional
- -D CIRRUS_CI=$ENV{CIRRUS_CI}
- -D CI_BUILD=${CI_BUILD}
- -P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
- DEPENDS ${FUNCTIONALTEST_PREREQS}
- USES_TERMINAL)
+add_dependencies(functionaltest test_deps)
+add_dependencies(benchmark test_deps)
diff --git a/test/README.md b/test/README.md
index 65a5ae7912..42d0ec0323 100644
--- a/test/README.md
+++ b/test/README.md
@@ -285,7 +285,7 @@ Number; !must be defined to function properly):
- `VALGRIND_LOG` (F) (S): overrides valgrind log file name used for `VALGRIND`.
-- `TEST_COLORS` (F) (U) (D): enable pretty colors in test runner.
+- `TEST_COLORS` (F) (U) (D): enable pretty colors in test runner. Set to true by default.
- `TEST_SKIP_FRAGILE` (F) (D): makes test suite skip some fragile tests.
diff --git a/test/busted/outputHandlers/nvim.lua b/test/busted/outputHandlers/nvim.lua
index e17536e0f8..4bfa21fe49 100644
--- a/test/busted/outputHandlers/nvim.lua
+++ b/test/busted/outputHandlers/nvim.lua
@@ -1,9 +1,15 @@
local pretty = require 'pl.pretty'
local global_helpers = require('test.helpers')
--- Colors are disabled by default. #15610
local colors = setmetatable({}, {__index = function() return function(s) return s == nil and '' or tostring(s) end end})
+
+local enable_colors = true
if os.getenv "TEST_COLORS" then
+ local test_colors = os.getenv("TEST_COLORS"):lower()
+ local disable_colors = test_colors == 'false' or test_colors == '0' or test_colors == 'no' or test_colors == 'off'
+ enable_colors = not disable_colors
+end
+if enable_colors then
colors = require 'term.colors'
end
diff --git a/test/busted_runner.lua b/test/busted_runner.lua
index 62d1e611e7..5604790069 100644
--- a/test/busted_runner.lua
+++ b/test/busted_runner.lua
@@ -1,12 +1,7 @@
local platform = vim.loop.os_uname()
-if platform and platform.sysname:lower():find'windows' then
- local deps_prefix = os.getenv 'DEPS_PREFIX'
- if deps_prefix ~= nil and deps_prefix ~= "" then
- package.path = deps_prefix.."/share/lua/5.1/?.lua;"..deps_prefix.."/share/lua/5.1/?/init.lua;"..package.path
- package.path = deps_prefix.."/bin/lua/?.lua;"..deps_prefix.."/bin/lua/?/init.lua;"..package.path
- package.cpath = deps_prefix.."/lib/lua/5.1/?.dll;"..package.cpath;
- package.cpath = deps_prefix.."/bin/?.dll;"..deps_prefix.."/bin/loadall.dll;"..package.cpath;
- end
-end
+local deps_install_dir = os.getenv 'DEPS_INSTALL_DIR'
+local suffix = (platform and platform.sysname:lower():find'windows') and '.dll' or '.so'
+package.path = deps_install_dir.."/share/lua/5.1/?.lua;"..deps_install_dir.."/share/lua/5.1/?/init.lua;"..package.path
+package.cpath = deps_install_dir.."/lib/lua/5.1/?"..suffix..";"..package.cpath;
require 'busted.runner'({ standalone = false })
diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua
index d454765edb..bf9e952319 100644
--- a/test/functional/api/buffer_spec.lua
+++ b/test/functional/api/buffer_spec.lua
@@ -630,19 +630,19 @@ describe('api/buf', function()
eq('Index out of bounds', pcall_err(get_offset, 6))
eq('Index out of bounds', pcall_err(get_offset, -1))
- curbufmeths.set_option('eol', false)
- curbufmeths.set_option('fixeol', false)
+ meths.set_option_value('eol', false, {})
+ meths.set_option_value('fixeol', false, {})
eq(28, get_offset(5))
-- fileformat is ignored
- curbufmeths.set_option('fileformat', 'dos')
+ meths.set_option_value('fileformat', 'dos', {})
eq(0, get_offset(0))
eq(6, get_offset(1))
eq(15, get_offset(2))
eq(16, get_offset(3))
eq(24, get_offset(4))
eq(28, get_offset(5))
- curbufmeths.set_option('eol', true)
+ meths.set_option_value('eol', true, {})
eq(29, get_offset(5))
command("set hidden")
@@ -697,23 +697,23 @@ describe('api/buf', function()
end)
end)
- describe('nvim_buf_get_option, nvim_buf_set_option', function()
+ describe('nvim_get_option_value, nvim_set_option_value', function()
it('works', function()
- eq(8, curbuf('get_option', 'shiftwidth'))
- curbuf('set_option', 'shiftwidth', 4)
- eq(4, curbuf('get_option', 'shiftwidth'))
+ eq(8, nvim('get_option_value', 'shiftwidth', {}))
+ nvim('set_option_value', 'shiftwidth', 4, {})
+ eq(4, nvim('get_option_value', 'shiftwidth', {}))
-- global-local option
- curbuf('set_option', 'define', 'test')
- eq('test', curbuf('get_option', 'define'))
+ nvim('set_option_value', 'define', 'test', {buf = 0})
+ eq('test', nvim('get_option_value', 'define', {buf = 0}))
-- Doesn't change the global value
- eq([[^\s*#\s*define]], nvim('get_option', 'define'))
+ eq([[^\s*#\s*define]], nvim('get_option_value', 'define', {scope='global'}))
end)
it('returns values for unset local options', function()
-- 'undolevels' is only set to its "unset" value when a new buffer is
-- created
command('enew')
- eq(-123456, curbuf('get_option', 'undolevels'))
+ eq(-123456, nvim('get_option_value', 'undolevels', {buf=0}))
end)
end)
diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua
index e30ffc92b6..675c8332de 100644
--- a/test/functional/api/extmark_spec.lua
+++ b/test/functional/api/extmark_spec.lua
@@ -1401,7 +1401,7 @@ describe('API/extmarks', function()
it('in read-only buffer', function()
command("view! runtime/doc/help.txt")
- eq(true, curbufmeths.get_option('ro'))
+ eq(true, meths.get_option_value('ro', {}))
local id = set_extmark(ns, 0, 0, 2)
eq({{id, 0, 2}}, get_extmarks(ns,0, -1))
end)
@@ -1474,7 +1474,7 @@ describe('API/extmarks', function()
it('in prompt buffer', function()
feed('dd')
local id = set_extmark(ns, marks[1], 0, 0, {})
- curbufmeths.set_option('buftype', 'prompt')
+ meths.set_option_value('buftype', 'prompt', {})
feed('i<esc>')
eq({{id, 0, 2}}, get_extmarks(ns, 0, -1))
end)
diff --git a/test/functional/api/highlight_spec.lua b/test/functional/api/highlight_spec.lua
index a6e9f9a42b..d3a79327ae 100644
--- a/test/functional/api/highlight_spec.lua
+++ b/test/functional/api/highlight_spec.lua
@@ -155,9 +155,9 @@ describe('API: highlight',function()
it("nvim_buf_add_highlight to other buffer doesn't crash if undo is disabled #12873", function()
command('vsplit file')
- local err, _ = pcall(meths.buf_set_option, 1, 'undofile', false)
+ local err, _ = pcall(meths.set_option_value, 'undofile', false, { buf = 1 })
eq(true, err)
- err, _ = pcall(meths.buf_set_option, 1, 'undolevels', -1)
+ err, _ = pcall(meths.set_option_value, 'undolevels', -1, { buf = 1 })
eq(true, err)
err, _ = pcall(meths.buf_add_highlight, 1, -1, 'Question', 0, 0, -1)
eq(true, err)
@@ -596,4 +596,9 @@ describe('API: get highlight', function()
eq({}, data["@foobar.hubbabubba"])
eq(nil, data["@foobar"])
end)
+
+ it('should return default flag', function()
+ meths.set_hl(0, 'Tried', { fg = "#00ff00", default = true })
+ eq({ fg = tonumber('00ff00', 16), default = true }, meths.get_hl(0, { name = 'Tried' }))
+ end)
end)
diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua
index f2817ff627..e239717d3a 100644
--- a/test/functional/api/keymap_spec.lua
+++ b/test/functional/api/keymap_spec.lua
@@ -813,19 +813,18 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
it('can make lua mappings', function()
eq(0, exec_lua [[
GlobalCount = 0
- vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]])
feed('asdf\n')
eq(1, exec_lua[[return GlobalCount]])
-
end)
it (':map command shows lua mapping correctly', function()
exec_lua [[
- vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() print('jkl;') end })
+ vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() print('jkl;') end })
]]
assert.truthy(
string.match(
@@ -837,7 +836,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
it ('mapcheck() returns lua mapping correctly', function()
exec_lua [[
- vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() print('jkl;') end })
+ vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() print('jkl;') end })
]]
assert.truthy(string.match(funcs.mapcheck('asdf', 'n'),
"^<Lua %d+>"))
@@ -871,7 +870,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
it('can make lua expr mappings replacing keycodes', function()
exec_lua [[
- vim.api.nvim_set_keymap ('n', 'aa', '', {callback = function() return '<Insert>π<C-V><M-π>foo<lt><Esc>' end, expr = true, replace_keycodes = true })
+ vim.api.nvim_set_keymap('n', 'aa', '', {callback = function() return '<Insert>π<C-V><M-π>foo<lt><Esc>' end, expr = true, replace_keycodes = true })
]]
feed('aa')
@@ -881,7 +880,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
it('can make lua expr mappings without replacing keycodes', function()
exec_lua [[
- vim.api.nvim_set_keymap ('i', 'aa', '', {callback = function() return '<space>' end, expr = true })
+ vim.api.nvim_set_keymap('i', 'aa', '', {callback = function() return '<space>' end, expr = true })
]]
feed('iaa<esc>')
@@ -891,7 +890,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
it('lua expr mapping returning nil is equivalent to returning an empty string', function()
exec_lua [[
- vim.api.nvim_set_keymap ('i', 'aa', '', {callback = function() return nil end, expr = true })
+ vim.api.nvim_set_keymap('i', 'aa', '', {callback = function() return nil end, expr = true })
]]
feed('iaa<esc>')
@@ -902,17 +901,29 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
it('does not reset pum in lua mapping', function()
eq(0, exec_lua [[
VisibleCount = 0
- vim.api.nvim_set_keymap ('i', '<F2>', '', {callback = function() VisibleCount = VisibleCount + vim.fn.pumvisible() end})
+ vim.api.nvim_set_keymap('i', '<F2>', '', {callback = function() VisibleCount = VisibleCount + vim.fn.pumvisible() end})
return VisibleCount
]])
feed('i<C-X><C-V><F2><F2><esc>')
eq(2, exec_lua[[return VisibleCount]])
end)
+ it('redo of lua mappings in op-pending mode work', function()
+ eq(0, exec_lua [[
+ OpCount = 0
+ vim.api.nvim_set_keymap('o', '<F2>', '', {callback = function() OpCount = OpCount + 1 end})
+ return OpCount
+ ]])
+ feed('d<F2>')
+ eq(1, exec_lua[[return OpCount]])
+ feed('.')
+ eq(2, exec_lua[[return OpCount]])
+ end)
+
it('can overwrite lua mappings', function()
eq(0, exec_lua [[
GlobalCount = 0
- vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]])
@@ -921,7 +932,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
eq(1, exec_lua[[return GlobalCount]])
exec_lua [[
- vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount - 1 end })
+ vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount - 1 end })
]]
feed('asdf\n')
@@ -932,7 +943,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
it('can unmap lua mappings', function()
eq(0, exec_lua [[
GlobalCount = 0
- vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]])
@@ -1078,7 +1089,7 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
it('can make lua mappings', function()
eq(0, exec_lua [[
GlobalCount = 0
- vim.api.nvim_buf_set_keymap (0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]])
@@ -1089,7 +1100,7 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
it('can make lua expr mappings replacing keycodes', function()
exec_lua [[
- vim.api.nvim_buf_set_keymap (0, 'n', 'aa', '', {callback = function() return '<Insert>π<C-V><M-π>foo<lt><Esc>' end, expr = true, replace_keycodes = true })
+ vim.api.nvim_buf_set_keymap(0, 'n', 'aa', '', {callback = function() return '<Insert>π<C-V><M-π>foo<lt><Esc>' end, expr = true, replace_keycodes = true })
]]
feed('aa')
@@ -1099,7 +1110,7 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
it('can make lua expr mappings without replacing keycodes', function()
exec_lua [[
- vim.api.nvim_buf_set_keymap (0, 'i', 'aa', '', {callback = function() return '<space>' end, expr = true })
+ vim.api.nvim_buf_set_keymap(0, 'i', 'aa', '', {callback = function() return '<space>' end, expr = true })
]]
feed('iaa<esc>')
@@ -1111,7 +1122,7 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
it('can overwrite lua mappings', function()
eq(0, exec_lua [[
GlobalCount = 0
- vim.api.nvim_buf_set_keymap (0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]])
@@ -1120,7 +1131,7 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
eq(1, exec_lua[[return GlobalCount]])
exec_lua [[
- vim.api.nvim_buf_set_keymap (0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount - 1 end })
+ vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount - 1 end })
]]
feed('asdf\n')
@@ -1131,7 +1142,7 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
it('can unmap lua mappings', function()
eq(0, exec_lua [[
GlobalCount = 0
- vim.api.nvim_buf_set_keymap (0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
]])
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index c81b6e90cc..040c26e058 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -1051,7 +1051,7 @@ describe('API', function()
line 3
]])
eq({0,4,1,0}, funcs.getpos('.')) -- Cursor follows the paste.
- eq(false, nvim('get_option', 'paste'))
+ eq(false, nvim('get_option_value', 'paste', {}))
command('%delete _')
-- Without final "\n".
nvim('paste', 'line 1\nline 2\nline 3', true, -1)
@@ -1091,7 +1091,7 @@ describe('API', function()
nvim('paste', 'line 1\r\n\r\rline 2\nline 3\rline 4\r', true, -1)
expect('line 1\n\n\nline 2\nline 3\nline 4\n')
eq({0,7,1,0}, funcs.getpos('.'))
- eq(false, nvim('get_option', 'paste'))
+ eq(false, nvim('get_option_value', 'paste', {}))
end)
it('Replace-mode', function()
-- Within single line
@@ -1382,44 +1382,38 @@ describe('API', function()
end)
end)
- describe('nvim_get_option, nvim_set_option', function()
+ describe('nvim_get_option_value, nvim_set_option_value', function()
it('works', function()
- ok(nvim('get_option', 'equalalways'))
- nvim('set_option', 'equalalways', false)
- ok(not nvim('get_option', 'equalalways'))
+ ok(nvim('get_option_value', 'equalalways', {}))
+ nvim('set_option_value', 'equalalways', false, {})
+ ok(not nvim('get_option_value', 'equalalways', {}))
end)
it('works to get global value of local options', function()
- eq(false, nvim('get_option', 'lisp'))
- eq(8, nvim('get_option', 'shiftwidth'))
+ eq(false, nvim('get_option_value', 'lisp', {}))
+ eq(8, nvim('get_option_value', 'shiftwidth', {}))
end)
it('works to set global value of local options', function()
- nvim('set_option', 'lisp', true)
- eq(true, nvim('get_option', 'lisp'))
- eq(false, helpers.curbuf('get_option', 'lisp'))
+ nvim('set_option_value', 'lisp', true, {scope='global'})
+ eq(true, nvim('get_option_value', 'lisp', {scope='global'}))
+ eq(false, nvim('get_option_value', 'lisp', {}))
eq(nil, nvim('command_output', 'setglobal lisp?'):match('nolisp'))
eq('nolisp', nvim('command_output', 'setlocal lisp?'):match('nolisp'))
- nvim('set_option', 'shiftwidth', 20)
+ nvim('set_option_value', 'shiftwidth', 20, {scope='global'})
eq('20', nvim('command_output', 'setglobal shiftwidth?'):match('%d+'))
eq('8', nvim('command_output', 'setlocal shiftwidth?'):match('%d+'))
end)
- it('most window-local options have no global value', function()
- local status, err = pcall(nvim, 'get_option', 'foldcolumn')
- eq(false, status)
- ok(err:match('Invalid option name') ~= nil)
- end)
-
it('updates where the option was last set from', function()
- nvim('set_option', 'equalalways', false)
+ nvim('set_option_value', 'equalalways', false, {})
local status, rv = pcall(nvim, 'command_output',
'verbose set equalalways?')
eq(true, status)
ok(nil ~= string.find(rv, 'noequalalways\n'..
'\tLast set from API client %(channel id %d+%)'))
- nvim('exec_lua', 'vim.api.nvim_set_option("equalalways", true)', {})
+ nvim('exec_lua', 'vim.api.nvim_set_option_value("equalalways", true, {})', {})
status, rv = pcall(nvim, 'command_output',
'verbose set equalalways?')
eq(true, status)
@@ -1499,8 +1493,7 @@ describe('API', function()
end)
it('set window options', function()
- -- Same as to nvim_win_set_option
- nvim('set_option_value', 'colorcolumn', '4,3', {win=0})
+ nvim('set_option_value', 'colorcolumn', '4,3', {})
eq('4,3', nvim('get_option_value', 'colorcolumn', {scope = 'local'}))
command("set modified hidden")
command("enew") -- edit new buffer, window option is preserved
@@ -1508,7 +1501,6 @@ describe('API', function()
end)
it('set local window options', function()
- -- Different to nvim_win_set_option
nvim('set_option_value', 'colorcolumn', '4,3', {win=0, scope='local'})
eq('4,3', nvim('get_option_value', 'colorcolumn', {win = 0, scope = 'local'}))
command("set modified hidden")
@@ -1519,11 +1511,11 @@ describe('API', function()
it('get buffer or window-local options', function()
nvim('command', 'new')
local buf = nvim('get_current_buf').id
- nvim('buf_set_option', buf, 'tagfunc', 'foobar')
+ nvim('set_option_value', 'tagfunc', 'foobar', {buf=buf})
eq('foobar', nvim('get_option_value', 'tagfunc', {buf = buf}))
local win = nvim('get_current_win').id
- nvim('win_set_option', win, 'number', true)
+ nvim('set_option_value', 'number', true, {win=win})
eq(true, nvim('get_option_value', 'number', {win = win}))
end)
@@ -2215,7 +2207,7 @@ describe('API', function()
it('stream=job :terminal channel', function()
command(':terminal')
eq({id=1}, meths.get_current_buf())
- eq(3, meths.buf_get_option(1, 'channel'))
+ eq(3, meths.get_option_value('channel', {buf=1}))
local info = {
stream='job',
@@ -2368,45 +2360,45 @@ describe('API', function()
end)
it('returns nothing with empty &runtimepath', function()
- meths.set_option('runtimepath', '')
+ meths.set_option_value('runtimepath', '', {})
eq({}, meths.list_runtime_paths())
end)
it('returns single runtimepath', function()
- meths.set_option('runtimepath', 'a')
+ meths.set_option_value('runtimepath', 'a', {})
eq({'a'}, meths.list_runtime_paths())
end)
it('returns two runtimepaths', function()
- meths.set_option('runtimepath', 'a,b')
+ meths.set_option_value('runtimepath', 'a,b', {})
eq({'a', 'b'}, meths.list_runtime_paths())
end)
it('returns empty strings when appropriate', function()
- meths.set_option('runtimepath', 'a,,b')
+ meths.set_option_value('runtimepath', 'a,,b', {})
eq({'a', '', 'b'}, meths.list_runtime_paths())
- meths.set_option('runtimepath', ',a,b')
+ meths.set_option_value('runtimepath', ',a,b', {})
eq({'', 'a', 'b'}, meths.list_runtime_paths())
-- Trailing "," is ignored. Use ",," if you really really want CWD.
- meths.set_option('runtimepath', 'a,b,')
+ meths.set_option_value('runtimepath', 'a,b,', {})
eq({'a', 'b'}, meths.list_runtime_paths())
- meths.set_option('runtimepath', 'a,b,,')
+ meths.set_option_value('runtimepath', 'a,b,,', {})
eq({'a', 'b', ''}, meths.list_runtime_paths())
end)
it('truncates too long paths', function()
local long_path = ('/a'):rep(8192)
- meths.set_option('runtimepath', long_path)
+ meths.set_option_value('runtimepath', long_path, {})
local paths_list = meths.list_runtime_paths()
eq({}, paths_list)
end)
end)
it('can throw exceptions', function()
- local status, err = pcall(nvim, 'get_option', 'invalid-option')
+ local status, err = pcall(nvim, 'get_option_value', 'invalid-option', {})
eq(false, status)
- ok(err:match('Invalid option name') ~= nil)
+ ok(err:match("Invalid 'option': 'invalid%-option'") ~= nil)
end)
it('does not truncate error message <1 MB #5984', function()
local very_long_name = 'A'..('x'):rep(10000)..'Z'
- local status, err = pcall(nvim, 'get_option', very_long_name)
+ local status, err = pcall(nvim, 'get_option_value', very_long_name, {})
eq(false, status)
eq(very_long_name, err:match('Ax+Z?'))
end)
@@ -2419,7 +2411,7 @@ describe('API', function()
describe('nvim_parse_expression', function()
before_each(function()
- meths.set_option('isident', '')
+ meths.set_option_value('isident', '', {})
end)
local function simplify_east_api_node(line, east_api_node)
@@ -2704,9 +2696,9 @@ describe('API', function()
end)
it('can change buftype before visiting', function()
- meths.set_option("hidden", false)
+ meths.set_option_value("hidden", false, {})
eq({id=2}, meths.create_buf(true, false))
- meths.buf_set_option(2, "buftype", "nofile")
+ meths.set_option_value("buftype", "nofile", {buf=2})
meths.buf_set_lines(2, 0, -1, true, {"test text"})
command("split | buffer 2")
eq({id=2}, meths.get_current_buf())
@@ -2749,10 +2741,10 @@ describe('API', function()
local edited_buf = 2
meths.buf_set_lines(edited_buf, 0, -1, true, {"some text"})
for _,b in ipairs(scratch_bufs) do
- eq('nofile', meths.buf_get_option(b, 'buftype'))
- eq('hide', meths.buf_get_option(b, 'bufhidden'))
- eq(false, meths.buf_get_option(b, 'swapfile'))
- eq(false, meths.buf_get_option(b, 'modeline'))
+ eq('nofile', meths.get_option_value('buftype', {buf=b}))
+ eq('hide', meths.get_option_value('bufhidden', {buf=b}))
+ eq(false, meths.get_option_value('swapfile', {buf=b}))
+ eq(false, meths.get_option_value('modeline', {buf=b}))
end
--
@@ -2765,10 +2757,10 @@ describe('API', function()
{1:~ }|
|
]])
- eq('nofile', meths.buf_get_option(edited_buf, 'buftype'))
- eq('hide', meths.buf_get_option(edited_buf, 'bufhidden'))
- eq(false, meths.buf_get_option(edited_buf, 'swapfile'))
- eq(false, meths.buf_get_option(edited_buf, 'modeline'))
+ eq('nofile', meths.get_option_value('buftype', {buf=edited_buf}))
+ eq('hide', meths.get_option_value('bufhidden', {buf=edited_buf}))
+ eq(false, meths.get_option_value('swapfile', {buf=edited_buf}))
+ eq(false, meths.get_option_value('modeline', {buf=edited_buf}))
-- Scratch buffer can be wiped without error.
command('bwipe')
@@ -2899,7 +2891,7 @@ describe('API', function()
it('should have information about global options', function()
-- precondition: the option was changed from its default
-- in test setup.
- eq(false, meths.get_option'showcmd')
+ eq(false, meths.get_option_value('showcmd', {}))
eq({
allows_duplicates = true,
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index ecab6a4713..a6d1807961 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -363,22 +363,22 @@ describe('API/win', function()
end)
end)
- describe('nvim_win_get_option, nvim_win_set_option', function()
+ describe('nvim_get_option_value, nvim_set_option_value', function()
it('works', function()
- curwin('set_option', 'colorcolumn', '4,3')
- eq('4,3', curwin('get_option', 'colorcolumn'))
+ nvim('set_option_value', 'colorcolumn', '4,3', {})
+ eq('4,3', nvim('get_option_value', 'colorcolumn', {}))
command("set modified hidden")
command("enew") -- edit new buffer, window option is preserved
- eq('4,3', curwin('get_option', 'colorcolumn'))
+ eq('4,3', nvim('get_option_value', 'colorcolumn', {}))
-- global-local option
- curwin('set_option', 'statusline', 'window-status')
- eq('window-status', curwin('get_option', 'statusline'))
- eq('', nvim('get_option', 'statusline'))
+ nvim('set_option_value', 'statusline', 'window-status', {win=0})
+ eq('window-status', nvim('get_option_value', 'statusline', {win=0}))
+ eq('', nvim('get_option_value', 'statusline', {scope='global'}))
command("set modified")
command("enew") -- global-local: not preserved in new buffer
-- confirm local value was not copied
- eq('', curwin('get_option', 'statusline'))
+ eq('', nvim('get_option_value', 'statusline', {win = 0}))
eq('', eval('&l:statusline'))
end)
@@ -386,16 +386,16 @@ describe('API/win', function()
nvim('command', 'tabnew')
local tab1 = unpack(nvim('list_tabpages'))
local win1 = unpack(tabpage('list_wins', tab1))
- window('set_option', win1, 'statusline', 'window-status')
+ nvim('set_option_value', 'statusline', 'window-status', {win=win1.id})
nvim('command', 'split')
nvim('command', 'wincmd J')
nvim('command', 'wincmd j')
- eq('window-status', window('get_option', win1, 'statusline'))
+ eq('window-status', nvim('get_option_value', 'statusline', {win = win1.id}))
assert_alive()
end)
it('returns values for unset local options', function()
- eq(-1, curwin('get_option', 'scrolloff'))
+ eq(-1, nvim('get_option_value', 'scrolloff', {win=0, scope='local'}))
end)
end)
@@ -568,11 +568,11 @@ describe('API/win', function()
it('deletes the buffer when bufhidden=wipe', function()
local oldwin = meths.get_current_win()
local oldbuf = meths.get_current_buf()
- local buf = meths.create_buf(true, false)
+ local buf = meths.create_buf(true, false).id
local newwin = meths.open_win(buf, true, {
relative='win', row=3, col=3, width=12, height=3
})
- meths.buf_set_option(buf, 'bufhidden', 'wipe')
+ meths.set_option_value('bufhidden', 'wipe', {buf=buf})
meths.win_hide(newwin)
eq({oldwin}, meths.list_wins())
eq({oldbuf}, meths.list_bufs())
diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua
index da8c7b5ee0..63a487c8bc 100644
--- a/test/functional/autocmd/autocmd_spec.lua
+++ b/test/functional/autocmd/autocmd_spec.lua
@@ -141,7 +141,7 @@ describe('autocmd', function()
describe('BufLeave autocommand', function()
it('can wipe out the buffer created by :edit which triggered autocmd',
function()
- meths.set_option('hidden', true)
+ meths.set_option_value('hidden', true, {})
curbufmeths.set_lines(0, 1, false, {
'start of test file xx',
'end of test file xx'})
diff --git a/test/functional/autocmd/cursorhold_spec.lua b/test/functional/autocmd/cursorhold_spec.lua
index b04bd5233a..e6bcb19682 100644
--- a/test/functional/autocmd/cursorhold_spec.lua
+++ b/test/functional/autocmd/cursorhold_spec.lua
@@ -26,7 +26,7 @@ describe('CursorHold', function()
-- if testing with small 'updatetime' fails, double its value and test again
retry(10, nil, function()
ut = ut * 2
- meths.set_option('updatetime', ut)
+ meths.set_option_value('updatetime', ut, {})
feed('0') -- reset did_cursorhold
meths.set_var('cursorhold', 0)
sleep(ut / 4)
@@ -51,12 +51,12 @@ describe('CursorHold', function()
end)
it("reducing 'updatetime' while waiting for CursorHold #20241", function()
- meths.set_option('updatetime', 10000)
+ meths.set_option_value('updatetime', 10000, {})
feed('0') -- reset did_cursorhold
meths.set_var('cursorhold', 0)
sleep(50)
eq(0, meths.get_var('cursorhold'))
- meths.set_option('updatetime', 20)
+ meths.set_option_value('updatetime', 20, {})
sleep(10)
eq(1, meths.get_var('cursorhold'))
end)
diff --git a/test/functional/autocmd/termxx_spec.lua b/test/functional/autocmd/termxx_spec.lua
index a9980dda04..9ec1469c03 100644
--- a/test/functional/autocmd/termxx_spec.lua
+++ b/test/functional/autocmd/termxx_spec.lua
@@ -16,14 +16,14 @@ local is_os = helpers.is_os
describe('autocmd TermClose', function()
before_each(function()
clear()
- nvim('set_option', 'shell', testprg('shell-test'))
+ nvim('set_option_value', 'shell', testprg('shell-test'), {})
command('set shellcmdflag=EXE shellredir= shellpipe= shellquote= shellxquote=')
end)
local function test_termclose_delete_own_buf()
-- The terminal process needs to keep running so that TermClose isn't triggered immediately.
- nvim('set_option', 'shell', string.format('"%s" INTERACT', testprg('shell-test')))
+ nvim('set_option_value', 'shell', string.format('"%s" INTERACT', testprg('shell-test')), {})
command('autocmd TermClose * bdelete!')
command('terminal')
matches('^TermClose Autocommands for "%*": Vim%(bdelete%):E937: Attempt to delete a buffer that is in use: term://',
@@ -51,7 +51,7 @@ describe('autocmd TermClose', function()
it('triggers when long-running terminal job gets stopped', function()
skip(is_os('win'))
- nvim('set_option', 'shell', is_os('win') and 'cmd.exe' or 'sh')
+ nvim('set_option_value', 'shell', is_os('win') and 'cmd.exe' or 'sh', {})
command('autocmd TermClose * let g:test_termclose = 23')
command('terminal')
command('call jobstop(b:terminal_job_id)')
@@ -60,8 +60,8 @@ describe('autocmd TermClose', function()
it('kills job trapping SIGTERM', function()
skip(is_os('win'))
- nvim('set_option', 'shell', 'sh')
- nvim('set_option', 'shellcmdflag', '-c')
+ nvim('set_option_value', 'shell', 'sh', {})
+ nvim('set_option_value', 'shellcmdflag', '-c', {})
command([[ let g:test_job = jobstart('trap "" TERM && echo 1 && sleep 60', { ]]
.. [[ 'on_stdout': {-> execute('let g:test_job_started = 1')}, ]]
.. [[ 'on_exit': {-> execute('let g:test_job_exited = 1')}}) ]])
@@ -80,8 +80,8 @@ describe('autocmd TermClose', function()
it('kills PTY job trapping SIGHUP and SIGTERM', function()
skip(is_os('win'))
- nvim('set_option', 'shell', 'sh')
- nvim('set_option', 'shellcmdflag', '-c')
+ nvim('set_option_value', 'shell', 'sh', {})
+ nvim('set_option_value', 'shellcmdflag', '-c', {})
command([[ let g:test_job = jobstart('trap "" HUP TERM && echo 1 && sleep 60', { ]]
.. [[ 'pty': 1,]]
.. [[ 'on_stdout': {-> execute('let g:test_job_started = 1')}, ]]
diff --git a/test/functional/core/spellfile_spec.lua b/test/functional/core/spellfile_spec.lua
index 378899eece..e3a59085cf 100644
--- a/test/functional/core/spellfile_spec.lua
+++ b/test/functional/core/spellfile_spec.lua
@@ -24,7 +24,7 @@ describe('spellfile', function()
-- │ ┌ Spell file version (#VIMSPELLVERSION)
local spellheader = 'VIMspell\050'
it('errors out when prefcond section is truncated', function()
- meths.set_option('runtimepath', testdir)
+ meths.set_option_value('runtimepath', testdir, {})
write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_PREFCOND)
-- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -34,12 +34,12 @@ describe('spellfile', function()
-- │ ┌ Condition length (1 byte)
-- │ │ ┌ Condition regex (missing!)
.. '\000\001\001')
- meths.set_option('spelllang', 'en')
+ meths.set_option_value('spelllang', 'en', {})
eq('Vim(set):E758: Truncated spell file',
exc_exec('set spell'))
end)
it('errors out when prefcond regexp contains NUL byte', function()
- meths.set_option('runtimepath', testdir)
+ meths.set_option_value('runtimepath', testdir, {})
write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_PREFCOND)
-- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -54,12 +54,12 @@ describe('spellfile', function()
-- │ ┌ KWORDTREE tree length (4 bytes)
-- │ │ ┌ PREFIXTREE tree length
.. '\000\000\000\000\000\000\000\000\000\000\000\000')
- meths.set_option('spelllang', 'en')
+ meths.set_option_value('spelllang', 'en', {})
eq('Vim(set):E759: Format error in spell file',
exc_exec('set spell'))
end)
it('errors out when region contains NUL byte', function()
- meths.set_option('runtimepath', testdir)
+ meths.set_option_value('runtimepath', testdir, {})
write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_REGION)
-- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -71,12 +71,12 @@ describe('spellfile', function()
-- │ ┌ KWORDTREE tree length (4 bytes)
-- │ │ ┌ PREFIXTREE tree length
.. '\000\000\000\000\000\000\000\000\000\000\000\000')
- meths.set_option('spelllang', 'en')
+ meths.set_option_value('spelllang', 'en', {})
eq('Vim(set):E759: Format error in spell file',
exc_exec('set spell'))
end)
it('errors out when SAL section contains NUL byte', function()
- meths.set_option('runtimepath', testdir)
+ meths.set_option_value('runtimepath', testdir, {})
write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_SAL)
-- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -95,15 +95,15 @@ describe('spellfile', function()
-- │ ┌ KWORDTREE tree length (4 bytes)
-- │ │ ┌ PREFIXTREE tree length
.. '\000\000\000\000\000\000\000\000\000\000\000\000')
- meths.set_option('spelllang', 'en')
+ meths.set_option_value('spelllang', 'en', {})
eq('Vim(set):E759: Format error in spell file',
exc_exec('set spell'))
end)
it('errors out when spell header contains NUL bytes', function()
- meths.set_option('runtimepath', testdir)
+ meths.set_option_value('runtimepath', testdir, {})
write_file(testdir .. '/spell/en.ascii.spl',
spellheader:sub(1, -3) .. '\000\000')
- meths.set_option('spelllang', 'en')
+ meths.set_option_value('spelllang', 'en', {})
eq('Vim(set):E757: This does not look like a spell file',
exc_exec('set spell'))
end)
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index b8a3c1dcd5..fe1b8e1c4e 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -40,9 +40,9 @@ end)
describe('startup', function()
it('--clean', function()
clear()
- ok(string.find(alter_slashes(meths.get_option('runtimepath')), funcs.stdpath('config'), 1, true) ~= nil)
+ ok(string.find(alter_slashes(meths.get_option_value('runtimepath', {})), funcs.stdpath('config'), 1, true) ~= nil)
clear('--clean')
- ok(string.find(alter_slashes(meths.get_option('runtimepath')), funcs.stdpath('config'), 1, true) == nil)
+ ok(string.find(alter_slashes(meths.get_option_value('runtimepath', {})), funcs.stdpath('config'), 1, true) == nil)
end)
it('--startuptime', function()
@@ -589,7 +589,7 @@ describe('startup', function()
]]
eq({'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
- local rtp = meths.get_option'rtp'
+ local rtp = meths.get_option_value('rtp', {})
ok(startswith(rtp, 'test/functional/fixtures/nvim,test/functional/fixtures/pack/*/start/*,test/functional/fixtures/start/*,test/functional/fixtures,test/functional/fixtures/middle,'),
'startswith(…)', 'rtp='..rtp)
end)
diff --git a/test/functional/editor/K_spec.lua b/test/functional/editor/K_spec.lua
index 3b5580540f..b964fb3467 100644
--- a/test/functional/editor/K_spec.lua
+++ b/test/functional/editor/K_spec.lua
@@ -59,7 +59,7 @@ describe('K', function()
end)
it('empty string falls back to :help #19298', function()
- meths.set_option('keywordprg', '')
+ meths.set_option_value('keywordprg', '', {})
meths.buf_set_lines(0, 0, -1, true, {'doesnotexist'})
feed('K')
eq('E149: Sorry, no help for doesnotexist', meths.get_vvar('errmsg'))
diff --git a/test/functional/editor/completion_spec.lua b/test/functional/editor/completion_spec.lua
index 22857efe5b..dcd7ef720f 100644
--- a/test/functional/editor/completion_spec.lua
+++ b/test/functional/editor/completion_spec.lua
@@ -988,7 +988,7 @@ describe('completion', function()
return ''
endfunction
]])
- meths.set_option('completeopt', 'menuone,noselect')
+ meths.set_option_value('completeopt', 'menuone,noselect', {})
meths.set_var('_complist', {{
word=0,
abbr=1,
diff --git a/test/functional/editor/mode_cmdline_spec.lua b/test/functional/editor/mode_cmdline_spec.lua
index 50cc5e17ee..fcd75ae3b6 100644
--- a/test/functional/editor/mode_cmdline_spec.lua
+++ b/test/functional/editor/mode_cmdline_spec.lua
@@ -55,7 +55,7 @@ describe('cmdline', function()
it('correctly clears end of the history', function()
-- Regression test: check absence of the memory leak when clearing end of
-- the history using ex_getln.c/clr_history().
- meths.set_option('history', 1)
+ meths.set_option_value('history', 1, {})
eq(1, funcs.histadd(':', 'foo'))
eq(1, funcs.histdel(':'))
eq('', funcs.histget(':', -1))
diff --git a/test/functional/ex_cmds/append_spec.lua b/test/functional/ex_cmds/append_spec.lua
index fadb5c9b42..4134eed87e 100644
--- a/test/functional/ex_cmds/append_spec.lua
+++ b/test/functional/ex_cmds/append_spec.lua
@@ -8,6 +8,7 @@ local clear = helpers.clear
local funcs = helpers.funcs
local command = helpers.command
local curbufmeths = helpers.curbufmeths
+local meths = helpers.meths
local Screen = require('test.functional.ui.screen')
local cmdtest = function(cmd, prep, ret1)
@@ -42,7 +43,7 @@ local cmdtest = function(cmd, prep, ret1)
eq(hisline, funcs.histget(':', -2))
eq(cmd, funcs.histget(':'))
-- Test that command-line window was launched
- eq('nofile', curbufmeths.get_option('buftype'))
+ eq('nofile', meths.get_option_value('buftype', {}))
eq('n', funcs.mode(1))
feed('<CR>')
eq('c', funcs.mode(1))
diff --git a/test/functional/ex_cmds/cmd_map_spec.lua b/test/functional/ex_cmds/cmd_map_spec.lua
index 919d167712..12867179bd 100644
--- a/test/functional/ex_cmds/cmd_map_spec.lua
+++ b/test/functional/ex_cmds/cmd_map_spec.lua
@@ -90,7 +90,7 @@ describe('mappings with <Cmd>', function()
{1:~ }|
{1:~ }|
{1:~ }|
- {2:E5521: <Cmd> mapping must end with <CR> before second <Cmd>} |
+ {2:E1136: <Cmd> mapping must end with <CR> before second <Cmd>} |
]])
command('noremap <F3> <Cmd>let x = 3')
@@ -103,7 +103,7 @@ describe('mappings with <Cmd>', function()
{1:~ }|
{1:~ }|
{1:~ }|
- {2:E5520: <Cmd> mapping must end with <CR>} |
+ {2:E1255: <Cmd> mapping must end with <CR>} |
]])
eq(0, eval('x'))
end)
diff --git a/test/functional/ex_cmds/ls_spec.lua b/test/functional/ex_cmds/ls_spec.lua
index 2583d80269..d02af21731 100644
--- a/test/functional/ex_cmds/ls_spec.lua
+++ b/test/functional/ex_cmds/ls_spec.lua
@@ -14,7 +14,7 @@ describe(':ls', function()
end)
it('R, F for :terminal buffers', function()
- nvim('set_option', 'shell', string.format('"%s" INTERACT', testprg('shell-test')))
+ nvim('set_option_value', 'shell', string.format('"%s" INTERACT', testprg('shell-test')), {})
command('edit foo')
command('set hidden')
diff --git a/test/functional/ex_cmds/make_spec.lua b/test/functional/ex_cmds/make_spec.lua
index 8d903330b1..d82f59ddf9 100644
--- a/test/functional/ex_cmds/make_spec.lua
+++ b/test/functional/ex_cmds/make_spec.lua
@@ -22,14 +22,14 @@ describe(':make', function()
end)
it('captures stderr & non zero exit code #14349', function ()
- nvim('set_option', 'makeprg', testprg('shell-test')..' foo')
+ nvim('set_option_value', 'makeprg', testprg('shell-test')..' foo', {})
local out = eval('execute("make")')
-- Error message is captured in the file and printed in the footer
matches('[\r\n]+.*[\r\n]+Unknown first argument%: foo[\r\n]+%(1 of 1%)%: Unknown first argument%: foo', out)
end)
it('captures stderr & zero exit code #14349', function ()
- nvim('set_option', 'makeprg', testprg('shell-test'))
+ nvim('set_option_value', 'makeprg', testprg('shell-test'), {})
local out = eval('execute("make")')
-- Ensure there are no "shell returned X" messages between
-- command and last line (indicating zero exit)
diff --git a/test/functional/ex_cmds/map_spec.lua b/test/functional/ex_cmds/map_spec.lua
index a197b81cc5..a580e88b93 100644
--- a/test/functional/ex_cmds/map_spec.lua
+++ b/test/functional/ex_cmds/map_spec.lua
@@ -18,7 +18,7 @@ describe(':*map', function()
it('are not affected by &isident', function()
meths.set_var('counter', 0)
command('nnoremap <C-x> :let counter+=1<CR>')
- meths.set_option('isident', ('%u'):format(('>'):byte()))
+ meths.set_option_value('isident', ('%u'):format(('>'):byte()), {})
command('nnoremap <C-y> :let counter+=1<CR>')
-- &isident used to disable keycode parsing here as well
feed('\24\25<C-x><C-y>')
diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua
index d70ccb5b39..7522d4a99c 100644
--- a/test/functional/ex_cmds/mksession_spec.lua
+++ b/test/functional/ex_cmds/mksession_spec.lua
@@ -81,13 +81,13 @@ describe(':mksession', function()
local buf_count = #meths.list_bufs()
eq(2, buf_count)
- eq('terminal', meths.buf_get_option(0, 'buftype'))
+ eq('terminal', meths.get_option_value('buftype', {}))
test_terminal_session_disabled(2)
-- no terminal should be set. As a side effect we end up with a blank buffer
- eq('', meths.buf_get_option(meths.list_bufs()[1], 'buftype'))
- eq('', meths.buf_get_option(meths.list_bufs()[2], 'buftype'))
+ eq('', meths.get_option_value('buftype', { buf = meths.list_bufs()[1] }))
+ eq('', meths.get_option_value('buftype', { buf = meths.list_bufs()[2] }))
end
)
@@ -112,7 +112,7 @@ describe(':mksession', function()
it('do not restore :terminal if not set in sessionoptions, only buffer #13078', function()
command('terminal')
- eq('terminal', meths.buf_get_option(0, 'buftype'))
+ eq('terminal', meths.get_option_value('buftype', {}))
local buf_count = #meths.list_bufs()
eq(1, buf_count)
@@ -120,7 +120,7 @@ describe(':mksession', function()
test_terminal_session_disabled(1)
-- no terminal should be set
- eq('', meths.buf_get_option(0, 'buftype'))
+ eq('', meths.get_option_value('buftype', {}))
end)
it('restores tab-local working directories', function()
@@ -249,7 +249,7 @@ describe(':mksession', function()
style = 'minimal',
}
meths.open_win(buf, false, config)
- local cmdheight = meths.get_option('cmdheight')
+ local cmdheight = meths.get_option_value('cmdheight', {})
command('mksession ' .. session_file)
-- Create a new test instance of Nvim.
@@ -262,7 +262,7 @@ describe(':mksession', function()
-- window was not restored.
eq(1, funcs.winnr('$'))
-- The command-line height should remain the same as it was.
- eq(cmdheight, meths.get_option('cmdheight'))
+ eq(cmdheight, meths.get_option_value('cmdheight', {}))
os.remove(tmpfile)
end)
diff --git a/test/functional/ex_cmds/source_spec.lua b/test/functional/ex_cmds/source_spec.lua
index 41045f5cb4..02f5bff021 100644
--- a/test/functional/ex_cmds/source_spec.lua
+++ b/test/functional/ex_cmds/source_spec.lua
@@ -48,7 +48,7 @@ describe(':source', function()
pending("'shellslash' only works on Windows")
return
end
- meths.set_option('shellslash', false)
+ meths.set_option_value('shellslash', false, {})
mkdir('Xshellslash')
write_file([[Xshellslash/Xstack.vim]], [[
diff --git a/test/functional/ex_cmds/verbose_spec.lua b/test/functional/ex_cmds/verbose_spec.lua
index def09e2f9e..50077e9e0c 100644
--- a/test/functional/ex_cmds/verbose_spec.lua
+++ b/test/functional/ex_cmds/verbose_spec.lua
@@ -18,7 +18,7 @@ local function last_set_tests(cmd)
script_location = table.concat{current_dir, helpers.get_pathsep(), script_file}
write_file(script_file, [[
-vim.api.nvim_set_option('hlsearch', false)
+vim.api.nvim_set_option_value('hlsearch', false, {})
vim.bo.expandtab = true
vim.opt.number = true
vim.api.nvim_set_keymap('n', '<leader>key1', ':echo "test"<cr>', {noremap = true})
@@ -160,7 +160,7 @@ describe('lua verbose:', function()
clear()
script_file = 'test_luafile.lua'
write_file(script_file, [[
- vim.api.nvim_set_option('hlsearch', false)
+ vim.api.nvim_set_option_value('hlsearch', false, {})
]])
exec(':source '..script_file)
end)
diff --git a/test/functional/ex_cmds/write_spec.lua b/test/functional/ex_cmds/write_spec.lua
index 126646f21a..0b8ce93b09 100644
--- a/test/functional/ex_cmds/write_spec.lua
+++ b/test/functional/ex_cmds/write_spec.lua
@@ -129,18 +129,18 @@ describe(':write', function()
eq(('Vim(write):E17: "'..funcs.fnamemodify('.', ':p:h')..'" is a directory'),
pcall_err(command, 'write .'))
end
- meths.set_option('writeany', true)
+ meths.set_option_value('writeany', true, {})
-- Message from buf_write
eq(('Vim(write):E502: "." is a directory'), pcall_err(command, 'write .'))
funcs.mkdir(fname_bak)
- meths.set_option('backupdir', '.')
- meths.set_option('backup', true)
+ meths.set_option_value('backupdir', '.', {})
+ meths.set_option_value('backup', true, {})
write_file(fname, 'content0')
command('edit ' .. fname)
funcs.setline(1, 'TTY')
eq('Vim(write):E510: Can\'t make backup file (add ! to override)',
pcall_err(command, 'write'))
- meths.set_option('backup', false)
+ meths.set_option_value('backup', false, {})
funcs.setfperm(fname, 'r--------')
eq('Vim(write):E505: "Xtest-functional-ex_cmds-write" is read-only (add ! to override)',
pcall_err(command, 'write'))
diff --git a/test/functional/legacy/012_directory_spec.lua b/test/functional/legacy/012_directory_spec.lua
index 050e3855fe..25d0dcb81e 100644
--- a/test/functional/legacy/012_directory_spec.lua
+++ b/test/functional/legacy/012_directory_spec.lua
@@ -15,7 +15,6 @@ local clear = helpers.clear
local insert = helpers.insert
local command = helpers.command
local write_file = helpers.write_file
-local curbufmeths = helpers.curbufmeths
local expect_exit = helpers.expect_exit
local mkdir = helpers.mkdir
@@ -58,9 +57,9 @@ describe("'directory' option", function()
line 3 Abcdefghij
end of testfile]])
- meths.set_option('swapfile', true)
- curbufmeths.set_option('swapfile', true)
- meths.set_option('directory', '.')
+ meths.set_option_value('swapfile', true, {})
+ meths.set_option_value('swapfile', true, {})
+ meths.set_option_value('directory', '.', {})
-- sanity check: files should not exist yet.
eq(nil, luv.fs_stat('.Xtest1.swp'))
@@ -72,7 +71,7 @@ describe("'directory' option", function()
-- reading the output from :!ls.
neq(nil, luv.fs_stat('.Xtest1.swp'))
- meths.set_option('directory', './Xtest2,.')
+ meths.set_option_value('directory', './Xtest2,.', {})
command('edit Xtest1')
poke_eventloop()
@@ -81,10 +80,10 @@ describe("'directory' option", function()
eq({ "Xtest1.swp", "Xtest3" }, ls_dir_sorted("Xtest2"))
- meths.set_option('directory', 'Xtest.je')
+ meths.set_option_value('directory', 'Xtest.je', {})
command('bdelete')
command('edit Xtest2/Xtest3')
- eq(true, curbufmeths.get_option('swapfile'))
+ eq(true, meths.get_option_value('swapfile', {}))
poke_eventloop()
eq({ "Xtest3" }, ls_dir_sorted("Xtest2"))
diff --git a/test/functional/legacy/autocmd_option_spec.lua b/test/functional/legacy/autocmd_option_spec.lua
index e00b468c16..8f17f509f5 100644
--- a/test/functional/legacy/autocmd_option_spec.lua
+++ b/test/functional/legacy/autocmd_option_spec.lua
@@ -631,24 +631,24 @@ describe('au OptionSet', function()
it('should trigger if a boolean option be set globally', function()
set_hook('autochdir')
- nvim.set_option('autochdir', true)
- eq(true, nvim.get_option('autochdir'))
+ nvim.set_option_value('autochdir', true, {scope='global'})
+ eq(true, nvim.get_option_value('autochdir', {scope='global'}))
expected_combination({'autochdir', 0, '', 0, 1, 'global', 'setglobal'})
end)
it('should trigger if a number option be set globally', function()
set_hook('cmdheight')
- nvim.set_option('cmdheight', 5)
- eq(5, nvim.get_option('cmdheight'))
+ nvim.set_option_value('cmdheight', 5, {scope='global'})
+ eq(5, nvim.get_option_value('cmdheight', {scope='global'}))
expected_combination({'cmdheight', 1, '', 1, 5, 'global', 'setglobal'})
end)
it('should trigger if a string option be set globally', function()
set_hook('ambiwidth')
- nvim.set_option('ambiwidth', 'double')
- eq('double', nvim.get_option('ambiwidth'))
+ nvim.set_option_value('ambiwidth', 'double', {scope='global'})
+ eq('double', nvim.get_option_value('ambiwidth', {scope='global'}))
expected_combination({'ambiwidth', 'single', '', 'single', 'double', 'global', 'setglobal'})
end)
end)
diff --git a/test/functional/legacy/buffer_spec.lua b/test/functional/legacy/buffer_spec.lua
index acaa9a51f1..1e8909f0d0 100644
--- a/test/functional/legacy/buffer_spec.lua
+++ b/test/functional/legacy/buffer_spec.lua
@@ -10,7 +10,7 @@ describe('buffer', function()
before_each(function()
clear()
meths.ui_attach(80, 24, {})
- meths.set_option('hidden', false)
+ meths.set_option_value('hidden', false, {})
end)
it('deleting a modified buffer with :confirm', function()
diff --git a/test/functional/legacy/cmdline_spec.lua b/test/functional/legacy/cmdline_spec.lua
index f7df6ae8d7..3cbff2a01b 100644
--- a/test/functional/legacy/cmdline_spec.lua
+++ b/test/functional/legacy/cmdline_spec.lua
@@ -225,9 +225,9 @@ describe('cmdline', function()
[3] = {reverse = true}, -- TabLineFill
})
screen:attach()
- meths.set_option('laststatus', 2)
- meths.set_option('showtabline', 2)
- meths.set_option('cmdheight', 1)
+ meths.set_option_value('laststatus', 2, {})
+ meths.set_option_value('showtabline', 2, {})
+ meths.set_option_value('cmdheight', 1, {})
screen:expect([[
{2: [No Name] }{3: }|
^ |
@@ -247,10 +247,10 @@ describe('cmdline', function()
[0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
}
screen:attach()
- meths.set_option('ruler', true)
- meths.set_option('rulerformat', 'longish')
- meths.set_option('laststatus', 0)
- meths.set_option('winwidth', 1)
+ meths.set_option_value('ruler', true, {})
+ meths.set_option_value('rulerformat', 'longish', {})
+ meths.set_option_value('laststatus', 0, {})
+ meths.set_option_value('winwidth', 1, {})
feed [[<C-W>v<C-W>|<C-W>p]]
screen:expect [[
│^ |
diff --git a/test/functional/legacy/display_spec.lua b/test/functional/legacy/display_spec.lua
index f1cd8d1aac..482b88eae8 100644
--- a/test/functional/legacy/display_spec.lua
+++ b/test/functional/legacy/display_spec.lua
@@ -196,17 +196,17 @@ describe('display', function()
end)
-- oldtest: Test_display_long_lastline()
- it('display "lastline" shows correct text when end of wrapped line is deleted', function()
+ it('"lastline" shows correct text when end of wrapped line is deleted', function()
local screen = Screen.new(35, 14)
screen:attach()
exec([[
- set display=lastline scrolloff=5
+ set display=lastline smoothscroll scrolloff=0
call setline(1, [
- \'aaaaa'->repeat(100),
+ \'aaaaa'->repeat(150),
\'bbbbb '->repeat(7) .. 'ccccc '->repeat(7) .. 'ddddd '->repeat(7)
\])
]])
- feed('482|')
+ feed('736|')
screen:expect([[
<<<aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
@@ -219,10 +219,11 @@ describe('display', function()
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaa^aaaaaaaaa|
- aaaaaaaaaa |
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ ^aaaaaaaaaaaaaaa |
|
]])
+ -- The correct part of the last line is moved into view.
feed('D')
screen:expect([[
<<<aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
@@ -236,9 +237,106 @@ describe('display', function()
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaa^a |
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^a|
bbbbb bbbbb bbbbb bbbbb bbbbb bb@@@|
|
]])
+ -- "w_skipcol" does not change because the topline is still long enough
+ -- to maintain the current skipcol.
+ feed('g04l11gkD')
+ screen:expect([[
+ <<<^a |
+ bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb|
+ bbbbb ccccc ccccc ccccc ccccc cccc|
+ c ccccc ccccc ddddd ddddd ddddd ddd|
+ dd ddddd ddddd ddddd |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]])
+ -- "w_skipcol" is reset to bring the entire topline into view because
+ -- the line length is now smaller than the current skipcol + marker.
+ feed('x')
+ screen:expect([[
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aa^a |
+ bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb|
+ bbbbb ccccc ccccc ccccc ccccc cccc|
+ c ccccc ccccc ddddd ddddd ddddd @@@|
+ |
+ ]])
+ end)
+
+ -- oldtest: Test_display_cursor_long_line()
+ it("correctly shows line that doesn't fit in the window", function()
+ local screen = Screen.new(75, 8)
+ screen:attach()
+ exec([[
+ call setline(1, ['a', 'b ' .. 'bbbbb'->repeat(150), 'c'])
+ norm $j
+ ]])
+ screen:expect([[
+ <<<bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ b^b |
+ |
+ ]])
+ -- FIXME: moving the cursor above the topline does not set w_skipcol
+ -- correctly with cpo+=n and zero scrolloff (curs_columns() extra == 1).
+ exec('set number cpo+=n scrolloff=0')
+ feed('$0')
+ screen:expect([[
+ <<<b^bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ |
+ ]])
+ -- Going to the start of the line with "b" did not set w_skipcol correctly with 'smoothscroll'.
+ exec('set smoothscroll')
+ feed('$b')
+ screen:expect([[
+ 2 b ^bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ |
+ ]])
+ -- Same for "ge".
+ feed('$ge')
+ screen:expect([[
+ 2 ^b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ |
+ ]])
end)
end)
diff --git a/test/functional/legacy/filechanged_spec.lua b/test/functional/legacy/filechanged_spec.lua
index cea1d6ac30..c8e772f597 100644
--- a/test/functional/legacy/filechanged_spec.lua
+++ b/test/functional/legacy/filechanged_spec.lua
@@ -12,8 +12,8 @@ describe('file changed dialog', function()
before_each(function()
clear()
meths.ui_attach(80, 24, {})
- meths.set_option('autoread', false)
- meths.set_option('fsync', true)
+ meths.set_option_value('autoread', false, {})
+ meths.set_option_value('fsync', true, {})
end)
it('works', function()
diff --git a/test/functional/legacy/messages_spec.lua b/test/functional/legacy/messages_spec.lua
index 71a53c8381..794676153c 100644
--- a/test/functional/legacy/messages_spec.lua
+++ b/test/functional/legacy/messages_spec.lua
@@ -361,9 +361,9 @@ describe('messages', function()
screen:attach()
command('cd '..nvim_dir)
- meths.set_option('shell', './shell-test')
- meths.set_option('shellcmdflag', 'REP 20')
- meths.set_option('shellxquote', '') -- win: avoid extra quotes
+ meths.set_option_value('shell', './shell-test', {})
+ meths.set_option_value('shellcmdflag', 'REP 20', {})
+ meths.set_option_value('shellxquote', '', {}) -- win: avoid extra quotes
-- display a page and go back, results in exactly the same view
feed([[:4 verbose echo system('foo')<CR>]])
diff --git a/test/functional/legacy/normal_spec.lua b/test/functional/legacy/normal_spec.lua
new file mode 100644
index 0000000000..ba875460f5
--- /dev/null
+++ b/test/functional/legacy/normal_spec.lua
@@ -0,0 +1,41 @@
+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)
+
+describe('normal', function()
+ -- 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()
+ screen:set_default_attr_ids({{foreground = Screen.colors.Brown}})
+ exec([[
+ set number foldmethod=diff scrolloff=0
+ call setline(1, map(range(1, 9), 'repeat(v:val, 200)'))
+ norm Lj
+ ]])
+ screen:expect([[
+ {1: 2 }222222222222222222222222222222222222|
+ {1: }222222222222222222222222222222222222|
+ {1: }222222222222222222222222222222222222|
+ {1: }222222222222222222222222222222222222|
+ {1: }222222222222222222222222222222222222|
+ {1: }22222222222222222222 |
+ {1: 3 }333333333333333333333333333333333333|
+ {1: }333333333333333333333333333333333333|
+ {1: }333333333333333333333333333333333333|
+ {1: }333333333333333333333333333333333333|
+ {1: }333333333333333333333333333333333333|
+ {1: }33333333333333333333 |
+ {1: 4 }^444444444444444444444444444444444444|
+ {1: }444444444444444444444444444444444444|
+ {1: }444444444444444444444444444444444444|
+ {1: }444444444444444444444444444444444444|
+ {1: }444444444444444444444444444444444444|
+ {1: }44444444444444444444 |
+ |
+ ]])
+ end)
+end)
diff --git a/test/functional/legacy/scroll_opt_spec.lua b/test/functional/legacy/scroll_opt_spec.lua
index c3c99b506b..cd4c2fda8b 100644
--- a/test/functional/legacy/scroll_opt_spec.lua
+++ b/test/functional/legacy/scroll_opt_spec.lua
@@ -428,7 +428,9 @@ describe('smoothscroll', function()
screen:expect_unchanged()
feed('G')
screen:expect_unchanged()
- -- moving cursor up right after the >>> marker - no need to show whole line
+ feed('4<C-Y>G')
+ screen:expect_unchanged()
+ -- moving cursor up right after the <<< marker - no need to show whole line
feed('2gj3l2k')
screen:expect([[
<<<^h some text with some text |
@@ -440,7 +442,7 @@ describe('smoothscroll', function()
with some text with some text |
|
]])
- -- moving cursor up where the >>> marker is - whole top line shows
+ -- moving cursor up where the <<< marker is - whole top line shows
feed('2j02k')
screen:expect([[
^Line with some text with some text with |
@@ -548,21 +550,21 @@ describe('smoothscroll', function()
exec('set scrolloff=0')
feed('0j')
screen:expect([[
- <<<of text with lots of text with lots o|
+ <<<th lots of text with lots of text wit|
+ h lots of text with lots of text with lo|
+ ts of text with lots of text with lots o|
f text with lots of text end |
^four |
- ~ |
- ~ |
|
]])
-- Test zt/zz/zb that they work properly when a long line is above it
- feed('zb')
+ feed('zt')
screen:expect([[
- <<<th lots of text with lots of text wit|
- h lots of text with lots of text with lo|
- ts of text with lots of text with lots o|
- f text with lots of text end |
^four |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
|
]])
feed('zz')
@@ -574,13 +576,13 @@ describe('smoothscroll', function()
~ |
|
]])
- feed('zt')
+ feed('zb')
screen:expect([[
+ <<<th lots of text with lots of text wit|
+ h lots of text with lots of text with lo|
+ ts of text with lots of text with lots o|
+ f text with lots of text end |
^four |
- ~ |
- ~ |
- ~ |
- ~ |
|
]])
-- Repeat the step and move the cursor down again.
@@ -588,15 +590,11 @@ describe('smoothscroll', function()
-- than one window. Note that the cursor is at the bottom this time because
-- Vim prefers to do so if we are scrolling a few lines only.
exec("call setline(1, ['one', 'two', 'Line' .. (' with lots of text'->repeat(10)) .. ' end', 'four'])")
+ -- Currently visible lines were replaced, test that the lines and cursor
+ -- are correctly displayed.
+ screen:expect_unchanged()
feed('3Gztj')
- screen:expect([[
- <<<th lots of text with lots of text wit|
- h lots of text with lots of text with lo|
- ts of text with lots of text with lots o|
- f text with lots of text end |
- ^four |
- |
- ]])
+ screen:expect_unchanged()
-- Repeat the step but this time start it when the line is smooth-scrolled by
-- one line. This tests that the offset calculation is still correct and
-- still end up scrolling down to the next line with cursor at bottom of
@@ -696,7 +694,7 @@ describe('smoothscroll', function()
end)
-- oldtest: Test_smoothscroll_ins_lines()
- it("this was unnecessarily inserting lines", function()
+ it("does not unnecessarily insert lines", function()
screen:try_resize(40, 6)
exec([=[
set wrap smoothscroll scrolloff=0 conceallevel=2 concealcursor=nc
@@ -719,6 +717,128 @@ describe('smoothscroll', function()
]])
end)
+ -- oldtest: Test_smoothscroll_cursormoved_line()
+ it("does not place the cursor in the command line", function()
+ screen:try_resize(40, 6)
+ exec([=[
+ set smoothscroll
+ call setline(1, [
+ \'',
+ \'_'->repeat(&lines * &columns),
+ \(('_')->repeat(&columns - 2) .. 'xxx')->repeat(2)
+ \])
+ autocmd CursorMoved * eval [line('w0'), line('w$')]
+ call search('xxx')
+ ]=])
+ screen:expect([[
+ <<<_____________________________________|
+ ________________________________________|
+ ______________________________________^xx|
+ x______________________________________x|
+ xx |
+ |
+ ]])
+ end)
+
+ -- oldtest: Test_smoothscroll_eob()
+ it("does not scroll halfway at end of buffer", function()
+ screen:try_resize(40, 10)
+ exec([[
+ set smoothscroll
+ call setline(1, ['']->repeat(100))
+ norm G
+ ]])
+ -- does not scroll halfway when scrolling to end of buffer
+ screen:expect([[
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ ^ |
+ |
+ ]])
+ exec("call setline(92, 'a'->repeat(100))")
+ feed('<C-B>G')
+ -- cursor is not placed below window
+ screen:expect([[
+ <<<aaaaaaaaaaaaaaaaa |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ ^ |
+ |
+ ]])
+ end)
+
+ -- oldtest: Test_smoothscroll_incsearch()
+ it("does not reset skipcol when doing incremental search on the same word", function()
+ screen:try_resize(40, 8)
+ screen:set_default_attr_ids({
+ [1] = {foreground = Screen.colors.Brown},
+ [2] = {foreground = Screen.colors.Blue1, bold = true},
+ [3] = {background = Screen.colors.Yellow1},
+ [4] = {reverse = true},
+ })
+ exec([[
+ set smoothscroll number scrolloff=0 incsearch
+ call setline(1, repeat([''], 20))
+ call setline(11, repeat('a', 100))
+ call setline(14, 'bbbb')
+ ]])
+ feed('/b')
+ screen:expect([[
+ {2:<<<}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {1: 12 } |
+ {1: 13 } |
+ {1: 14 }{4:b}{3:bbb} |
+ {1: 15 } |
+ {1: 16 } |
+ {1: 17 } |
+ /b^ |
+ ]])
+ feed('b')
+ screen:expect([[
+ {2:<<<}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {1: 12 } |
+ {1: 13 } |
+ {1: 14 }{4:bb}{3:bb} |
+ {1: 15 } |
+ {1: 16 } |
+ {1: 17 } |
+ /bb^ |
+ ]])
+ feed('b')
+ screen:expect([[
+ {2:<<<}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {1: 12 } |
+ {1: 13 } |
+ {1: 14 }{4:bbb}b |
+ {1: 15 } |
+ {1: 16 } |
+ {1: 17 } |
+ /bbb^ |
+ ]])
+ feed('b')
+ screen:expect([[
+ {2:<<<}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+ {1: 12 } |
+ {1: 13 } |
+ {1: 14 }{4:bbbb} |
+ {1: 15 } |
+ {1: 16 } |
+ {1: 17 } |
+ /bbbb^ |
+ ]])
+ end)
+
it("works with virt_lines above and below", function()
screen:try_resize(55, 7)
exec([=[
diff --git a/test/functional/legacy/vimscript_spec.lua b/test/functional/legacy/vimscript_spec.lua
index f59a87f824..16a1080396 100644
--- a/test/functional/legacy/vimscript_spec.lua
+++ b/test/functional/legacy/vimscript_spec.lua
@@ -12,7 +12,7 @@ describe('Vim script', function()
it('Error when if/for/while/try/function is nested too deep',function()
local screen = Screen.new(80, 24)
screen:attach()
- meths.set_option('laststatus', 2)
+ meths.set_option_value('laststatus', 2, {})
exec([[
" Deep nesting of if ... endif
func Test1()
diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua
index 04f4f89472..d415b708be 100644
--- a/test/functional/lua/buffer_updates_spec.lua
+++ b/test/functional/lua/buffer_updates_spec.lua
@@ -415,7 +415,7 @@ describe('lua: nvim_buf_attach on_bytes', function()
it('opening lines', function()
local check_events = setup_eventcheck(verify, origlines)
- -- meths.buf_set_option(0, 'autoindent', true)
+ -- meths.set_option_value('autoindent', true, {})
feed 'Go'
check_events {
{ "test1", "bytes", 1, 4, 7, 0, 114, 0, 0, 0, 1, 0, 1 };
@@ -428,7 +428,7 @@ describe('lua: nvim_buf_attach on_bytes', function()
it('opening lines with autoindent', function()
local check_events = setup_eventcheck(verify, origlines)
- meths.buf_set_option(0, 'autoindent', true)
+ meths.set_option_value('autoindent', true, {})
feed 'Go'
check_events {
{ "test1", "bytes", 1, 4, 7, 0, 114, 0, 0, 0, 1, 0, 5 };
@@ -462,8 +462,8 @@ describe('lua: nvim_buf_attach on_bytes', function()
it('continuing comments with fo=or', function()
local check_events = setup_eventcheck(verify, {'// Comment'})
- meths.buf_set_option(0, 'formatoptions', 'ro')
- meths.buf_set_option(0, 'filetype', 'c')
+ meths.set_option_value('formatoptions', 'ro', {})
+ meths.set_option_value('filetype', 'c', {})
feed 'A<CR>'
check_events {
{ "test1", "bytes", 1, 4, 0, 10, 10, 0, 0, 0, 1, 3, 4 };
@@ -603,7 +603,7 @@ describe('lua: nvim_buf_attach on_bytes', function()
it('inccomand=nosplit and substitute', function()
local check_events = setup_eventcheck(verify,
{"abcde", "12345"})
- meths.set_option('inccommand', 'nosplit')
+ meths.set_option_value('inccommand', 'nosplit', {})
-- linewise substitute
feed(':%s/bcd/')
@@ -998,7 +998,7 @@ describe('lua: nvim_buf_attach on_bytes', function()
it("virtual edit", function ()
local check_events = setup_eventcheck(verify, { "", " " })
- meths.set_option("virtualedit", "all")
+ meths.set_option_value('virtualedit', "all", {})
feed [[<Right><Right>iab<ESC>]]
diff --git a/test/functional/lua/command_line_completion_spec.lua b/test/functional/lua/command_line_completion_spec.lua
index 9a0d534358..177e077f4a 100644
--- a/test/functional/lua/command_line_completion_spec.lua
+++ b/test/functional/lua/command_line_completion_spec.lua
@@ -31,14 +31,12 @@ describe('nlua_expand_pat', function()
eq(
{{
'nvim_buf_set_lines',
- 'nvim_buf_set_option'
}, 8
},
get_completions('vim.api.nvim_buf_', {
vim = {
api = {
nvim_buf_set_lines = true,
- nvim_buf_set_option = true,
nvim_win_doesnt_match = true,
},
other_key = true,
@@ -68,14 +66,12 @@ describe('nlua_expand_pat', function()
eq(
{{
'nvim_buf_set_lines',
- 'nvim_buf_set_option'
}, 11
},
get_completions('vim["api"].nvim_buf_', {
vim = {
api = {
nvim_buf_set_lines = true,
- nvim_buf_set_option = true,
nvim_win_doesnt_match = true,
},
other_key = true,
@@ -88,7 +84,6 @@ describe('nlua_expand_pat', function()
eq(
{{
'nvim_buf_set_lines',
- 'nvim_buf_set_option'
}, 21
},
get_completions('vim["nested"]["api"].nvim_buf_', {
@@ -96,7 +91,6 @@ describe('nlua_expand_pat', function()
nested = {
api = {
nvim_buf_set_lines = true,
- nvim_buf_set_option = true,
nvim_win_doesnt_match = true,
},
},
@@ -121,7 +115,6 @@ describe('nlua_expand_pat', function()
eq(
{{
'nvim_buf_set_lines',
- 'nvim_buf_set_option'
}, 12
},
get_completions('vim[MY_VAR].nvim_buf_', {
@@ -129,7 +122,6 @@ describe('nlua_expand_pat', function()
vim = {
api = {
nvim_buf_set_lines = true,
- nvim_buf_set_option = true,
nvim_win_doesnt_match = true,
},
other_key = true,
diff --git a/test/functional/lua/filetype_spec.lua b/test/functional/lua/filetype_spec.lua
index 540eae1c9b..b3d95e1c7f 100644
--- a/test/functional/lua/filetype_spec.lua
+++ b/test/functional/lua/filetype_spec.lua
@@ -134,6 +134,6 @@ end)
describe('filetype.lua', function()
it('does not override user autocommands that set filetype #20333', function()
clear({args={'--clean', '--cmd', 'autocmd BufRead *.md set filetype=notmarkdown', 'README.md'}})
- eq('notmarkdown', meths.buf_get_option(0, 'filetype'))
+ eq('notmarkdown', meths.get_option_value('filetype', {}))
end)
end)
diff --git a/test/functional/lua/fs_spec.lua b/test/functional/lua/fs_spec.lua
index 2fcbc9450f..aae0ed91a7 100644
--- a/test/functional/lua/fs_spec.lua
+++ b/test/functional/lua/fs_spec.lua
@@ -223,7 +223,7 @@ describe('vim.fs', function()
describe('find()', function()
it('works', function()
- eq({test_build_dir}, exec_lua([[
+ eq({test_build_dir .. "/build"}, exec_lua([[
local dir = ...
return vim.fs.find('build', { path = dir, upward = true, type = 'directory' })
]], nvim_dir))
@@ -239,7 +239,7 @@ describe('vim.fs', function()
end)
it('accepts predicate as names', function()
- eq({test_build_dir}, exec_lua([[
+ eq({test_build_dir .. "/build"}, exec_lua([[
local dir = ...
local opts = { path = dir, upward = true, type = 'directory' }
return vim.fs.find(function(x) return x == 'build' end, opts)
@@ -266,6 +266,17 @@ describe('vim.fs', function()
end)
end)
+ describe('joinpath()', function()
+ it('works', function()
+ eq('foo/bar/baz', exec_lua([[
+ return vim.fs.joinpath('foo', 'bar', 'baz')
+ ]], nvim_dir))
+ eq('foo/bar/baz', exec_lua([[
+ return vim.fs.joinpath('foo', '/bar/', '/baz')
+ ]], nvim_dir))
+ end)
+ end)
+
describe('normalize()', function()
it('works with backward slashes', function()
eq('C:/Users/jdoe', exec_lua [[ return vim.fs.normalize('C:\\Users\\jdoe') ]])
diff --git a/test/functional/lua/inspector_spec.lua b/test/functional/lua/inspector_spec.lua
index f9ec274290..c369956e56 100644
--- a/test/functional/lua/inspector_spec.lua
+++ b/test/functional/lua/inspector_spec.lua
@@ -18,8 +18,8 @@ describe('vim.inspect_pos', function()
vim.api.nvim_set_current_buf(buf)
vim.api.nvim_buf_set_lines(0, 0, -1, false, {"local a = 123"})
vim.api.nvim_buf_set_lines(buf1, 0, -1, false, {"--commentline"})
- vim.api.nvim_buf_set_option(buf, "filetype", "lua")
- vim.api.nvim_buf_set_option(buf1, "filetype", "lua")
+ vim.bo[buf].filetype = 'lua'
+ vim.bo[buf1].filetype = 'lua'
vim.api.nvim_buf_set_extmark(buf, ns1, 0, 10, { hl_group = "Normal" })
vim.api.nvim_buf_set_extmark(buf, ns2, 0, 10, { hl_group = "Normal" })
vim.cmd("syntax on")
@@ -97,7 +97,7 @@ describe('vim.show_pos', function()
local buf = vim.api.nvim_create_buf(true, false)
vim.api.nvim_set_current_buf(buf)
vim.api.nvim_buf_set_lines(0, 0, -1, false, {"local a = 123"})
- vim.api.nvim_buf_set_option(buf, "filetype", "lua")
+ vim.bo[buf].filetype = 'lua'
vim.cmd("syntax on")
return {buf, vim.show_pos(0, 0, 10)}
]])
diff --git a/test/functional/lua/luaeval_spec.lua b/test/functional/lua/luaeval_spec.lua
index 613008b5e1..dfbd2fb18b 100644
--- a/test/functional/lua/luaeval_spec.lua
+++ b/test/functional/lua/luaeval_spec.lua
@@ -514,7 +514,7 @@ describe('v:lua', function()
[5] = {bold = true, foreground = Screen.colors.SeaGreen4},
})
screen:attach()
- meths.buf_set_option(0, 'omnifunc', 'v:lua.mymod.omni')
+ meths.set_option_value('omnifunc', 'v:lua.mymod.omni', {})
feed('isome st<c-x><c-o>')
screen:expect{grid=[[
some stuff^ |
@@ -526,7 +526,7 @@ describe('v:lua', function()
{1:~ }|
{4:-- Omni completion (^O^N^P) }{5:match 1 of 3} |
]]}
- meths.set_option('operatorfunc', 'v:lua.mymod.noisy')
+ meths.set_option_value('operatorfunc', 'v:lua.mymod.noisy', {})
feed('<Esc>g@g@')
eq("hey line", meths.get_current_line())
end)
diff --git a/test/functional/lua/overrides_spec.lua b/test/functional/lua/overrides_spec.lua
index f88698f83d..68e2525151 100644
--- a/test/functional/lua/overrides_spec.lua
+++ b/test/functional/lua/overrides_spec.lua
@@ -100,7 +100,7 @@ describe('print', function()
pcall_err(command, 'lua bad_custom_error()'))
end)
it('prints strings with NULs and NLs correctly', function()
- meths.set_option('more', true)
+ meths.set_option_value('more', true, {})
eq('abc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT\n',
exec_capture([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\n")]]))
eq('abc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT^@',
diff --git a/test/functional/lua/runtime_spec.lua b/test/functional/lua/runtime_spec.lua
index 72c99ac1f3..cd19ea4e49 100644
--- a/test/functional/lua/runtime_spec.lua
+++ b/test/functional/lua/runtime_spec.lua
@@ -61,6 +61,38 @@ describe('runtime:', function()
eq('vim', eval('g:colorscheme'))
end)
+
+ it("loads lua colorscheme in 'rtp' if vim version only exists in 'pp' #23724", function()
+ local pack_dir = 'Test_Pack'
+ mkdir_p(pack_dir)
+ finally(function()
+ rmdir(pack_dir)
+ end)
+ exec('set pp+=' .. pack_dir)
+
+ local pack_opt_dir = pack_dir .. sep .. 'pack' .. sep .. 'some_name' .. sep .. 'opt'
+ local colors_opt_dir = pack_opt_dir .. sep .. 'some_pack' .. sep .. 'colors'
+ mkdir_p(colors_opt_dir)
+
+ local rtp_colorscheme_file = colorscheme_folder .. sep .. 'new_colorscheme'
+ local pp_opt_colorscheme_file = colors_opt_dir .. sep .. 'new_colorscheme'
+
+ write_file(pp_opt_colorscheme_file .. '.lua', [[vim.g.colorscheme = 'lua_pp']])
+ exec('colorscheme new_colorscheme')
+ eq('lua_pp', eval('g:colorscheme'))
+
+ write_file(pp_opt_colorscheme_file .. '.vim', [[let g:colorscheme = 'vim_pp']])
+ exec('colorscheme new_colorscheme')
+ eq('vim_pp', eval('g:colorscheme'))
+
+ write_file(rtp_colorscheme_file .. '.lua', [[vim.g.colorscheme = 'lua_rtp']])
+ exec('colorscheme new_colorscheme')
+ eq('lua_rtp', eval('g:colorscheme'))
+
+ write_file(rtp_colorscheme_file .. '.vim', [[let g:colorscheme = 'vim_rtp']])
+ exec('colorscheme new_colorscheme')
+ eq('vim_rtp', eval('g:colorscheme'))
+ end)
end)
describe('compiler', function()
diff --git a/test/functional/lua/secure_spec.lua b/test/functional/lua/secure_spec.lua
index 2348a193de..fc20a06390 100644
--- a/test/functional/lua/secure_spec.lua
+++ b/test/functional/lua/secure_spec.lua
@@ -6,7 +6,7 @@ local clear = helpers.clear
local command = helpers.command
local pathsep = helpers.get_pathsep()
local is_os = helpers.is_os
-local curbufmeths = helpers.curbufmeths
+local meths = helpers.meths
local exec_lua = helpers.exec_lua
local feed_command = helpers.feed_command
local feed = helpers.feed
@@ -160,7 +160,7 @@ describe('vim.secure', function()
-- Cannot write file
pcall_err(command, 'write')
- eq(true, curbufmeths.get_option('readonly'))
+ eq(true, meths.get_option_value('readonly', {}))
end)
end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 86eb600bd9..978a4fe0b6 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -1496,9 +1496,9 @@ describe('lua stdlib', function()
it('vim.bo', function()
eq('', funcs.luaeval "vim.bo.filetype")
exec_lua [[
- vim.api.nvim_buf_set_option(0, "filetype", "markdown")
+ vim.api.nvim_set_option_value("filetype", "markdown", {})
BUF = vim.api.nvim_create_buf(false, true)
- vim.api.nvim_buf_set_option(BUF, "modifiable", false)
+ vim.api.nvim_set_option_value("modifiable", false, {buf = BUF})
]]
eq(false, funcs.luaeval "vim.bo.modified")
eq('markdown', funcs.luaeval "vim.bo.filetype")
@@ -1519,9 +1519,9 @@ describe('lua stdlib', function()
it('vim.wo', function()
exec_lua [[
- vim.api.nvim_win_set_option(0, "cole", 2)
+ vim.api.nvim_set_option_value("cole", 2, {})
vim.cmd "split"
- vim.api.nvim_win_set_option(0, "cole", 2)
+ vim.api.nvim_set_option_value("cole", 2, {})
]]
eq(2, funcs.luaeval "vim.wo.cole")
exec_lua [[
@@ -1566,8 +1566,8 @@ describe('lua stdlib', function()
local result = exec_lua [[
local result = {}
- table.insert(result, vim.api.nvim_get_option('scrolloff'))
- table.insert(result, vim.api.nvim_win_get_option(0, 'scrolloff'))
+ table.insert(result, vim.api.nvim_get_option_value('scrolloff', {scope='global'}))
+ table.insert(result, vim.api.nvim_get_option_value('scrolloff', {win=0}))
return result
]]
@@ -1631,20 +1631,20 @@ describe('lua stdlib', function()
local result = {}
vim.opt.makeprg = "global-local"
- table.insert(result, vim.api.nvim_get_option('makeprg'))
- table.insert(result, vim.api.nvim_buf_get_option(0, 'makeprg'))
+ table.insert(result, vim.go.makeprg)
+ table.insert(result, vim.api.nvim_get_option_value('makeprg', {buf=0}))
vim.opt_local.mp = "only-local"
- table.insert(result, vim.api.nvim_get_option('makeprg'))
- table.insert(result, vim.api.nvim_buf_get_option(0, 'makeprg'))
+ table.insert(result, vim.go.makeprg)
+ table.insert(result, vim.api.nvim_get_option_value('makeprg', {buf=0}))
vim.opt_global.makeprg = "only-global"
- table.insert(result, vim.api.nvim_get_option('makeprg'))
- table.insert(result, vim.api.nvim_buf_get_option(0, 'makeprg'))
+ table.insert(result, vim.go.makeprg)
+ table.insert(result, vim.api.nvim_get_option_value('makeprg', {buf=0}))
vim.opt.makeprg = "global-local"
- table.insert(result, vim.api.nvim_get_option('makeprg'))
- table.insert(result, vim.api.nvim_buf_get_option(0, 'makeprg'))
+ table.insert(result, vim.go.makeprg)
+ table.insert(result, vim.api.nvim_get_option_value('makeprg', {buf=0}))
return result
]]
@@ -2173,7 +2173,7 @@ describe('lua stdlib', function()
it('can handle isfname ,,,', function()
local result = exec_lua [[
vim.opt.isfname = "a,b,,,c"
- return { vim.opt.isfname:get(), vim.api.nvim_get_option('isfname') }
+ return { vim.opt.isfname:get(), vim.go.isfname }
]]
eq({{",", "a", "b", "c"}, "a,b,,,c"}, result)
@@ -2183,7 +2183,7 @@ describe('lua stdlib', function()
it('can handle isfname ,^,,', function()
local result = exec_lua [[
vim.opt.isfname = "a,b,^,,c"
- return { vim.opt.isfname:get(), vim.api.nvim_get_option('isfname') }
+ return { vim.opt.isfname:get(), vim.go.isfname }
]]
eq({{"^,", "a", "b", "c"}, "a,b,^,,c"}, result)
@@ -2734,14 +2734,14 @@ describe('lua stdlib', function()
describe('vim.api.nvim_buf_call', function()
it('can access buf options', function()
- local buf1 = meths.get_current_buf()
+ local buf1 = meths.get_current_buf().id
local buf2 = exec_lua [[
buf2 = vim.api.nvim_create_buf(false, true)
return buf2
]]
- eq(false, meths.buf_get_option(buf1, 'autoindent'))
- eq(false, meths.buf_get_option(buf2, 'autoindent'))
+ eq(false, meths.get_option_value('autoindent', {buf=buf1}))
+ eq(false, meths.get_option_value('autoindent', {buf=buf2}))
local val = exec_lua [[
return vim.api.nvim_buf_call(buf2, function()
@@ -2750,9 +2750,9 @@ describe('lua stdlib', function()
end)
]]
- eq(false, meths.buf_get_option(buf1, 'autoindent'))
- eq(true, meths.buf_get_option(buf2, 'autoindent'))
- eq(buf1, meths.get_current_buf())
+ eq(false, meths.get_option_value('autoindent', {buf=buf1}))
+ eq(true, meths.get_option_value('autoindent', {buf=buf2}))
+ eq(buf1, meths.get_current_buf().id)
eq(buf2, val)
end)
@@ -2771,10 +2771,10 @@ describe('lua stdlib', function()
eq(true, exec_lua([[
local function scratch_buf_call(fn)
local buf = vim.api.nvim_create_buf(false, true)
- vim.api.nvim_buf_set_option(buf, 'cindent', true)
+ vim.api.nvim_set_option_value('cindent', true, {buf = buf})
return vim.api.nvim_buf_call(buf, function()
return vim.api.nvim_get_current_buf() == buf
- and vim.api.nvim_buf_get_option(buf, 'cindent')
+ and vim.api.nvim_get_option_value('cindent', {buf = buf})
and fn()
end) and vim.api.nvim_buf_delete(buf, {}) == nil
end
@@ -2811,7 +2811,7 @@ describe('lua stdlib', function()
describe('vim.api.nvim_win_call', function()
it('can access window options', function()
command('vsplit')
- local win1 = meths.get_current_win()
+ local win1 = meths.get_current_win().id
command('wincmd w')
local win2 = exec_lua [[
win2 = vim.api.nvim_get_current_win()
@@ -2819,8 +2819,8 @@ describe('lua stdlib', function()
]]
command('wincmd p')
- eq('', meths.win_get_option(win1, 'winhighlight'))
- eq('', meths.win_get_option(win2, 'winhighlight'))
+ eq('', meths.get_option_value('winhighlight', {win=win1}))
+ eq('', meths.get_option_value('winhighlight', {win=win2}))
local val = exec_lua [[
return vim.api.nvim_win_call(win2, function()
@@ -2829,9 +2829,9 @@ describe('lua stdlib', function()
end)
]]
- eq('', meths.win_get_option(win1, 'winhighlight'))
- eq('Normal:Normal', meths.win_get_option(win2, 'winhighlight'))
- eq(win1, meths.get_current_win())
+ eq('', meths.get_option_value('winhighlight', {win=win1}))
+ eq('Normal:Normal', meths.get_option_value('winhighlight', {win=win2}))
+ eq(win1, meths.get_current_win().id)
eq(win2, val)
end)
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index fcf313785a..3690b7e97c 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -202,8 +202,8 @@ describe('startup defaults', function()
clear{args={}, args_rm={'-i'}, env=env}
-- Default 'shadafile' is empty.
-- This means use the default location. :help shada-file-name
- eq('', meths.get_option('shadafile'))
- eq('', meths.get_option('viminfofile'))
+ eq('', meths.get_option_value('shadafile', {}))
+ eq('', meths.get_option_value('viminfofile', {}))
-- Check that shada data (such as v:oldfiles) is saved/restored.
command('edit Xtest-foo')
command('write')
@@ -227,13 +227,13 @@ describe('startup defaults', function()
args_rm={'runtimepath'},
}
-- Defaults to &runtimepath.
- eq(meths.get_option('runtimepath'), meths.get_option('packpath'))
+ eq(meths.get_option_value('runtimepath', {}), meths.get_option_value('packpath', {}))
-- Does not follow modifications to runtimepath.
meths.command('set runtimepath+=foo')
- neq(meths.get_option('runtimepath'), meths.get_option('packpath'))
+ neq(meths.get_option_value('runtimepath', {}), meths.get_option_value('packpath', {}))
meths.command('set packpath+=foo')
- eq(meths.get_option('runtimepath'), meths.get_option('packpath'))
+ eq(meths.get_option_value('runtimepath', {}), meths.get_option_value('packpath', {}))
end)
it('v:progpath is set to the absolute path', function()
@@ -318,10 +318,10 @@ describe('XDG defaults', function()
USER=nil,
}})
- eq('.', meths.get_option('backupdir'))
- eq('.', meths.get_option('viewdir'))
- eq('.', meths.get_option('directory'))
- eq('.', meths.get_option('undodir'))
+ eq('.', meths.get_option_value('backupdir', {}))
+ eq('.', meths.get_option_value('viewdir', {}))
+ eq('.', meths.get_option_value('directory', {}))
+ eq('.', meths.get_option_value('undodir', {}))
ok((funcs.tempname()):len() > 4)
end)
end)
@@ -383,7 +383,7 @@ describe('XDG defaults', function()
.. ',' .. root_path .. ('/b'):rep(2048) .. '/nvim/after'
.. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim/after'
.. ',' .. root_path .. ('/x'):rep(4096) .. '/nvim/after'
- ):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
+ ):gsub('\\', '/')), (meths.get_option_value('runtimepath', {})):gsub('\\', '/'))
meths.command('set runtimepath&')
meths.command('set backupdir&')
meths.command('set directory&')
@@ -407,15 +407,15 @@ describe('XDG defaults', function()
.. ',' .. root_path .. ('/b'):rep(2048) .. '/nvim/after'
.. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim/after'
.. ',' .. root_path .. ('/x'):rep(4096) .. '/nvim/after'
- ):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
+ ):gsub('\\', '/')), (meths.get_option_value('runtimepath', {})):gsub('\\', '/'))
eq('.,' .. root_path .. ('/X'):rep(4096).. '/' .. state_dir .. '/backup//',
- (meths.get_option('backupdir'):gsub('\\', '/')))
+ (meths.get_option_value('backupdir', {}):gsub('\\', '/')))
eq(root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/swap//',
- (meths.get_option('directory')):gsub('\\', '/'))
+ (meths.get_option_value('directory', {})):gsub('\\', '/'))
eq(root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/undo//',
- (meths.get_option('undodir')):gsub('\\', '/'))
+ (meths.get_option_value('undodir', {})):gsub('\\', '/'))
eq(root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/view//',
- (meths.get_option('viewdir')):gsub('\\', '/'))
+ (meths.get_option_value('viewdir', {})):gsub('\\', '/'))
end)
end)
@@ -450,7 +450,7 @@ describe('XDG defaults', function()
.. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site/after'
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
- ):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
+ ):gsub('\\', '/')), (meths.get_option_value('runtimepath', {})):gsub('\\', '/'))
meths.command('set runtimepath&')
meths.command('set backupdir&')
meths.command('set directory&')
@@ -466,15 +466,15 @@ describe('XDG defaults', function()
.. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site/after'
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
- ):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
+ ):gsub('\\', '/')), (meths.get_option_value('runtimepath', {})):gsub('\\', '/'))
eq(('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
- meths.get_option('backupdir'):gsub('\\', '/'))
+ meths.get_option_value('backupdir', {}):gsub('\\', '/'))
eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
- meths.get_option('directory'):gsub('\\', '/'))
+ meths.get_option_value('directory', {}):gsub('\\', '/'))
eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
- meths.get_option('undodir'):gsub('\\', '/'))
+ meths.get_option_value('undodir', {}):gsub('\\', '/'))
eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
- meths.get_option('viewdir'):gsub('\\', '/'))
+ meths.get_option_value('viewdir', {}):gsub('\\', '/'))
meths.command('set all&')
eq(('$XDG_DATA_HOME/nvim'
.. ',$XDG_DATA_DIRS/nvim'
@@ -486,15 +486,15 @@ describe('XDG defaults', function()
.. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site/after'
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
- ):gsub('\\', '/'), (meths.get_option('runtimepath')):gsub('\\', '/'))
+ ):gsub('\\', '/'), (meths.get_option_value('runtimepath', {})):gsub('\\', '/'))
eq(('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
- meths.get_option('backupdir'):gsub('\\', '/'))
+ meths.get_option_value('backupdir', {}):gsub('\\', '/'))
eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
- meths.get_option('directory'):gsub('\\', '/'))
+ meths.get_option_value('directory', {}):gsub('\\', '/'))
eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
- meths.get_option('undodir'):gsub('\\', '/'))
+ meths.get_option_value('undodir', {}):gsub('\\', '/'))
eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
- meths.get_option('viewdir'):gsub('\\', '/'))
+ meths.get_option_value('viewdir', {}):gsub('\\', '/'))
eq(nil, (funcs.tempname()):match('XDG_RUNTIME_DIR'))
end)
end)
@@ -529,7 +529,7 @@ describe('XDG defaults', function()
.. ',-\\,-\\,-' .. path_sep .. 'nvim' .. path_sep .. 'after'
.. ',\\,-\\,-\\,' .. path_sep .. 'nvim' .. path_sep .. 'after'
.. ',\\, \\, \\,' .. path_sep .. 'nvim' .. path_sep .. 'after'
- ), meths.get_option('runtimepath'))
+ ), meths.get_option_value('runtimepath', {}))
meths.command('set runtimepath&')
meths.command('set backupdir&')
meths.command('set directory&')
@@ -549,15 +549,15 @@ describe('XDG defaults', function()
.. ',-\\,-\\,-' .. path_sep ..'nvim' .. path_sep ..'after'
.. ',\\,-\\,-\\,' .. path_sep ..'nvim' .. path_sep ..'after'
.. ',\\, \\, \\,' .. path_sep ..'nvim' .. path_sep ..'after'
- ), meths.get_option('runtimepath'))
+ ), meths.get_option_value('runtimepath', {}))
eq('.,\\,=\\,=\\,' .. path_sep .. state_dir .. '' .. path_sep ..'backup' .. (path_sep):rep(2),
- meths.get_option('backupdir'))
+ meths.get_option_value('backupdir', {}))
eq('\\,=\\,=\\,' .. path_sep ..'' .. state_dir .. '' .. path_sep ..'swap' .. (path_sep):rep(2),
- meths.get_option('directory'))
+ meths.get_option_value('directory', {}))
eq('\\,=\\,=\\,' .. path_sep ..'' .. state_dir .. '' .. path_sep ..'undo' .. (path_sep):rep(2),
- meths.get_option('undodir'))
+ meths.get_option_value('undodir', {}))
eq('\\,=\\,=\\,' .. path_sep ..'' .. state_dir .. '' .. path_sep ..'view' .. (path_sep):rep(2),
- meths.get_option('viewdir'))
+ meths.get_option_value('viewdir', {}))
end)
end)
end)
diff --git a/test/functional/options/num_options_spec.lua b/test/functional/options/num_options_spec.lua
index f343e2da75..16a53c75e6 100644
--- a/test/functional/options/num_options_spec.lua
+++ b/test/functional/options/num_options_spec.lua
@@ -11,7 +11,7 @@ local function should_fail(opt, value, errmsg)
feed_command('setlocal ' .. opt .. '=' .. value)
eq(errmsg, eval("v:errmsg"):match("E%d*"))
feed_command('let v:errmsg = ""')
- local status, err = pcall(meths.set_option, opt, value)
+ local status, err = pcall(meths.set_option_value, opt, value, {})
eq(status, false)
eq(errmsg, err:match("E%d*"))
eq('', eval("v:errmsg"))
@@ -20,8 +20,8 @@ end
local function should_succeed(opt, value)
feed_command('setglobal ' .. opt .. '=' .. value)
feed_command('setlocal ' .. opt .. '=' .. value)
- meths.set_option(opt, value)
- eq(value, meths.get_option(opt))
+ meths.set_option_value(opt, value, {})
+ eq(value, meths.get_option_value(opt, {}))
eq('', eval("v:errmsg"))
end
@@ -29,12 +29,12 @@ describe(':setlocal', function()
before_each(clear)
it('setlocal sets only local value', function()
- eq(0, meths.get_option('iminsert'))
+ eq(0, meths.get_option_value('iminsert', {scope='global'}))
feed_command('setlocal iminsert=1')
- eq(0, meths.get_option('iminsert'))
- eq(-1, meths.get_option('imsearch'))
+ eq(0, meths.get_option_value('iminsert', {scope='global'}))
+ eq(-1, meths.get_option_value('imsearch', {scope='global'}))
feed_command('setlocal imsearch=1')
- eq(-1, meths.get_option('imsearch'))
+ eq(-1, meths.get_option_value('imsearch', {scope='global'}))
end)
end)
@@ -77,8 +77,8 @@ describe(':set validation', function()
-- If smaller than 1 this one is set to 'lines'-1
feed_command('setglobal window=-10')
- meths.set_option('window', -10)
- eq(23, meths.get_option('window'))
+ meths.set_option_value('window', -10, {})
+ eq(23, meths.get_option_value('window', {}))
eq('', eval("v:errmsg"))
-- 'scrolloff' and 'sidescrolloff' can have a -1 value when
@@ -112,8 +112,8 @@ describe(':set validation', function()
local function setto(value)
feed_command('setglobal maxcombine=' .. value)
feed_command('setlocal maxcombine=' .. value)
- meths.set_option('maxcombine', value)
- eq(6, meths.get_option('maxcombine'))
+ meths.set_option_value('maxcombine', value, {})
+ eq(6, meths.get_option_value('maxcombine', {}))
eq('', eval("v:errmsg"))
end
setto(0)
diff --git a/test/functional/plugin/editorconfig_spec.lua b/test/functional/plugin/editorconfig_spec.lua
index e6a2550aba..4ad9903032 100644
--- a/test/functional/plugin/editorconfig_spec.lua
+++ b/test/functional/plugin/editorconfig_spec.lua
@@ -3,7 +3,6 @@ local clear = helpers.clear
local command = helpers.command
local eq = helpers.eq
local pathsep = helpers.get_pathsep()
-local curbufmeths = helpers.curbufmeths
local funcs = helpers.funcs
local meths = helpers.meths
@@ -13,7 +12,7 @@ local function test_case(name, expected)
local filename = testdir .. pathsep .. name
command('edit ' .. filename)
for opt, val in pairs(expected) do
- eq(val, curbufmeths.get_option(opt), name)
+ eq(val, meths.get_option_value(opt, {buf=0}), name)
end
end
diff --git a/test/functional/plugin/lsp/incremental_sync_spec.lua b/test/functional/plugin/lsp/incremental_sync_spec.lua
index 4985da9cd7..724b3efb97 100644
--- a/test/functional/plugin/lsp/incremental_sync_spec.lua
+++ b/test/functional/plugin/lsp/incremental_sync_spec.lua
@@ -21,7 +21,7 @@ before_each(function ()
-- ["mac"] = '\r',
-- }
- -- local line_ending = format_line_ending[vim.api.nvim_buf_get_option(0, 'fileformat')]
+ -- local line_ending = format_line_ending[vim.api.nvim_get_option_value('fileformat', {})]
function test_register(bufnr, id, offset_encoding, line_ending)
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 5ba0706208..b906ae265f 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -33,7 +33,9 @@ local test_rpc_server = lsp_helpers.test_rpc_server
local function get_buf_option(name, bufnr)
bufnr = bufnr or "BUFFER"
- return exec_lua(string.format("return vim.api.nvim_buf_get_option(%s, '%s')", bufnr, name))
+ return exec_lua(
+ string.format("return vim.api.nvim_get_option_value('%s', { buf = %s })", name, bufnr)
+ )
end
-- TODO(justinmk): hangs on Windows https://github.com/neovim/neovim/pull/11837
@@ -356,8 +358,8 @@ describe('LSP', function()
vim.api.nvim_command('filetype plugin on')
BUFFER_1 = vim.api.nvim_create_buf(false, true)
BUFFER_2 = vim.api.nvim_create_buf(false, true)
- vim.api.nvim_buf_set_option(BUFFER_1, 'filetype', 'man')
- vim.api.nvim_buf_set_option(BUFFER_2, 'filetype', 'xml')
+ vim.api.nvim_set_option_value('filetype', 'man', { buf = BUFFER_1 })
+ vim.api.nvim_set_option_value('filetype', 'xml', { buf = BUFFER_2 })
]]
-- Sanity check to ensure that some values are set after setting filetype.
@@ -394,9 +396,9 @@ describe('LSP', function()
client = _client
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
- vim.api.nvim_buf_set_option(BUFFER, 'tagfunc', 'tfu')
- vim.api.nvim_buf_set_option(BUFFER, 'omnifunc', 'ofu')
- vim.api.nvim_buf_set_option(BUFFER, 'formatexpr', 'fex')
+ vim.api.nvim_set_option_value('tagfunc', 'tfu', { buf = BUFFER })
+ vim.api.nvim_set_option_value('omnifunc', 'ofu', { buf = BUFFER })
+ vim.api.nvim_set_option_value('formatexpr', 'fex', { buf = BUFFER })
lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)
]]
end;
@@ -1166,7 +1168,7 @@ describe('LSP', function()
"testing";
"123";
})
- vim.api.nvim_buf_set_option(BUFFER, 'eol', false)
+ vim.bo[BUFFER].eol = false
]]
end;
on_init = function(_client)
@@ -2929,8 +2931,8 @@ describe('LSP', function()
describe('lsp.util.get_effective_tabstop', function()
local function test_tabstop(tabsize, shiftwidth)
exec_lua(string.format([[
- vim.api.nvim_buf_set_option(0, 'shiftwidth', %d)
- vim.api.nvim_buf_set_option(0, 'tabstop', 2)
+ vim.bo.shiftwidth = %d
+ vim.bo.tabstop = 2
]], shiftwidth))
eq(tabsize, exec_lua('return vim.lsp.util.get_effective_tabstop()'))
end
@@ -3778,6 +3780,13 @@ describe('LSP', function()
name = 'watchfiles-test',
cmd = server.cmd,
root_dir = root_dir,
+ capabilities = {
+ workspace = {
+ didChangeWatchedFiles = {
+ dynamicRegistration = true,
+ },
+ },
+ },
})
local expected_messages = 2 -- initialize, initialized
@@ -3855,7 +3864,7 @@ describe('LSP', function()
end)
it('correctly registers and unregisters', function()
- local root_dir = 'some_dir'
+ local root_dir = '/some_dir'
exec_lua(create_server_definition)
local result = exec_lua([[
local root_dir = ...
@@ -3865,6 +3874,13 @@ describe('LSP', function()
name = 'watchfiles-test',
cmd = server.cmd,
root_dir = root_dir,
+ capabilities = {
+ workspace = {
+ didChangeWatchedFiles = {
+ dynamicRegistration = true,
+ },
+ },
+ },
})
local expected_messages = 2 -- initialize, initialized
@@ -3982,6 +3998,13 @@ describe('LSP', function()
name = 'watchfiles-test',
cmd = server.cmd,
root_dir = root_dir,
+ capabilities = {
+ workspace = {
+ didChangeWatchedFiles = {
+ dynamicRegistration = true,
+ },
+ },
+ },
})
local expected_messages = 2 -- initialize, initialized
@@ -4009,10 +4032,9 @@ describe('LSP', function()
local watchers = {}
local max_kind = protocol.WatchKind.Create + protocol.WatchKind.Change + protocol.WatchKind.Delete
for i = 0, max_kind do
- local j = i
table.insert(watchers, {
globPattern = {
- baseUri = vim.uri_from_fname('/dir'..tostring(i)),
+ baseUri = vim.uri_from_fname('/dir'),
pattern = 'watch'..tostring(i),
},
kind = i,
@@ -4031,7 +4053,7 @@ describe('LSP', function()
}, { client_id = client_id })
for i = 0, max_kind do
- local filename = 'watch'..tostring(i)
+ local filename = '/dir/watch' .. tostring(i)
send_event(filename, vim._watch.FileChangeType.Created)
send_event(filename, vim._watch.FileChangeType.Changed)
send_event(filename, vim._watch.FileChangeType.Deleted)
@@ -4045,7 +4067,8 @@ describe('LSP', function()
local function watched_uri(fname)
return exec_lua([[
- return vim.uri_from_fname(...)
+ local fname = ...
+ return vim.uri_from_fname('/dir/' .. fname)
]], fname)
end
@@ -4116,6 +4139,13 @@ describe('LSP', function()
name = 'watchfiles-test',
cmd = server.cmd,
root_dir = root_dir,
+ capabilities = {
+ workspace = {
+ didChangeWatchedFiles = {
+ dynamicRegistration = true,
+ },
+ },
+ },
})
local expected_messages = 2 -- initialize, initialized
@@ -4186,5 +4216,61 @@ describe('LSP', function()
},
}, result[3].params)
end)
+
+ it("ignores registrations by servers when the client doesn't advertise support", function()
+ exec_lua(create_server_definition)
+ local result = exec_lua([[
+ local server = _create_server()
+ local client_id = vim.lsp.start({
+ name = 'watchfiles-test',
+ cmd = server.cmd,
+ root_dir = 'some_dir',
+ capabilities = {
+ workspace = {
+ didChangeWatchedFiles = {
+ dynamicRegistration = false,
+ },
+ },
+ },
+ })
+
+ local watching = false
+ require('vim.lsp._watchfiles')._watchfunc = function(_, _, callback)
+ -- Since the registration is ignored, this should not execute and `watching` should stay false
+ watching = true
+ return function() end
+ end
+
+ vim.lsp.handlers['client/registerCapability'](nil, {
+ registrations = {
+ {
+ id = 'watchfiles-test-kind',
+ method = 'workspace/didChangeWatchedFiles',
+ registerOptions = {
+ watchers = {
+ {
+ globPattern = '**/*',
+ },
+ },
+ },
+ },
+ },
+ }, { client_id = client_id })
+
+ -- Ensure no errors occur when unregistering something that was never really registered.
+ vim.lsp.handlers['client/unregisterCapability'](nil, {
+ unregisterations = {
+ {
+ id = 'watchfiles-test-kind',
+ method = 'workspace/didChangeWatchedFiles',
+ },
+ },
+ }, { client_id = client_id })
+
+ return watching
+ ]])
+
+ eq(false, result)
+ end)
end)
end)
diff --git a/test/functional/plugin/man_spec.lua b/test/functional/plugin/man_spec.lua
index 9730bf4bf6..d5c1a78fc8 100644
--- a/test/functional/plugin/man_spec.lua
+++ b/test/functional/plugin/man_spec.lua
@@ -20,10 +20,10 @@ local function get_search_history(name)
local man = require('runtime.lua.man')
local res = {}
man.find_path = function(sect, name)
- table.insert(res, name)
+ table.insert(res, {sect, name})
return nil
end
- local ok, rv = pcall(man.open_page, 0, {tab = 0}, args)
+ local ok, rv = pcall(man.open_page, -1, {tab = 0}, args)
assert(not ok)
assert(rv and rv:match('no manual entry'))
return res
@@ -196,16 +196,32 @@ describe(':Man', function()
it('tries variants with spaces, underscores #22503', function()
eq({
- 'NAME WITH SPACES',
- 'NAME_WITH_SPACES',
+ {'', 'NAME WITH SPACES'},
+ {'', 'NAME_WITH_SPACES'},
}, get_search_history('NAME WITH SPACES'))
eq({
- 'some other man',
- 'some_other_man',
+ {'3', 'some other man'},
+ {'3', 'some_other_man'},
}, get_search_history('3 some other man'))
eq({
- 'other_man',
- 'other_man',
+ {'3x', 'some other man'},
+ {'3x', 'some_other_man'},
+ }, get_search_history('3X some other man'))
+ eq({
+ {'3tcl', 'some other man'},
+ {'3tcl', 'some_other_man'},
+ }, get_search_history('3tcl some other man'))
+ eq({
+ {'n', 'some other man'},
+ {'n', 'some_other_man'},
+ }, get_search_history('n some other man'))
+ eq({
+ {'', '123some other man'},
+ {'', '123some_other_man'},
+ }, get_search_history('123some other man'))
+ eq({
+ {'1', 'other_man'},
+ {'1', 'other_man'},
}, get_search_history('other_man(1)'))
end)
end)
diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua
index f6145a5809..8d37100607 100644
--- a/test/functional/plugin/shada_spec.lua
+++ b/test/functional/plugin/shada_spec.lua
@@ -2181,8 +2181,8 @@ describe('plugin/shada.vim', function()
' - contents "ab"',
' - "a"',
}, nvim_eval('getline(1, "$")'))
- eq(false, curbuf('get_option', 'modified'))
- eq('shada', curbuf('get_option', 'filetype'))
+ eq(false, nvim('get_option_value', 'modified', {}))
+ eq('shada', nvim('get_option_value', 'filetype', {}))
nvim_command('edit ' .. fname_tmp)
eq({
'History entry with timestamp ' .. epoch .. ':',
@@ -2191,8 +2191,8 @@ describe('plugin/shada.vim', function()
' - contents "ab"',
' - "b"',
}, nvim_eval('getline(1, "$")'))
- eq(false, curbuf('get_option', 'modified'))
- eq('shada', curbuf('get_option', 'filetype'))
+ eq(false, nvim('get_option_value', 'modified', {}))
+ eq('shada', nvim('get_option_value', 'filetype', {}))
eq('++opt not supported', exc_exec('edit ++enc=latin1 ' .. fname))
neq({
'History entry with timestamp ' .. epoch .. ':',
@@ -2201,7 +2201,7 @@ describe('plugin/shada.vim', function()
' - contents "ab"',
' - "a"',
}, nvim_eval('getline(1, "$")'))
- neq(true, curbuf('get_option', 'modified'))
+ neq(true, nvim('get_option_value', 'modified', {}))
end)
it('event FileReadCmd', function()
@@ -2217,8 +2217,8 @@ describe('plugin/shada.vim', function()
' - contents "ab"',
' - "a"',
}, nvim_eval('getline(1, "$")'))
- eq(true, curbuf('get_option', 'modified'))
- neq('shada', curbuf('get_option', 'filetype'))
+ eq(true, nvim('get_option_value', 'modified', {}))
+ neq('shada', nvim('get_option_value', 'filetype', {}))
nvim_command('1,$read ' .. fname_tmp)
eq({
'',
@@ -2233,9 +2233,9 @@ describe('plugin/shada.vim', function()
' - contents "ab"',
' - "b"',
}, nvim_eval('getline(1, "$")'))
- eq(true, curbuf('get_option', 'modified'))
- neq('shada', curbuf('get_option', 'filetype'))
- curbuf('set_option', 'modified', false)
+ eq(true, nvim('get_option_value', 'modified', {}))
+ neq('shada', nvim('get_option_value', 'filetype', {}))
+ nvim('set_option_value', 'modified', false, {})
eq('++opt not supported', exc_exec('$read ++enc=latin1 ' .. fname))
eq({
'',
@@ -2250,7 +2250,7 @@ describe('plugin/shada.vim', function()
' - contents "ab"',
' - "b"',
}, nvim_eval('getline(1, "$")'))
- neq(true, curbuf('get_option', 'modified'))
+ neq(true, nvim('get_option_value', 'modified', {}))
end)
it('event BufWriteCmd', function()
@@ -2517,10 +2517,10 @@ describe('ftplugin/shada.vim', function()
it('sets options correctly', function()
nvim_command('filetype plugin indent on')
nvim_command('setlocal filetype=shada')
- eq(true, curbuf('get_option', 'expandtab'))
- eq(2, curbuf('get_option', 'tabstop'))
- eq(2, curbuf('get_option', 'softtabstop'))
- eq(2, curbuf('get_option', 'shiftwidth'))
+ eq(true, nvim('get_option_value', 'expandtab', {}))
+ eq(2, nvim('get_option_value', 'tabstop', {}))
+ eq(2, nvim('get_option_value', 'softtabstop', {}))
+ eq(2, nvim('get_option_value', 'shiftwidth', {}))
end)
it('sets indentkeys correctly', function()
diff --git a/test/functional/provider/perl_spec.lua b/test/functional/provider/perl_spec.lua
index 5ab807e90d..8049f0f3e2 100644
--- a/test/functional/provider/perl_spec.lua
+++ b/test/functional/provider/perl_spec.lua
@@ -5,7 +5,7 @@ local command = helpers.command
local write_file = helpers.write_file
local eval = helpers.eval
local retry = helpers.retry
-local curbufmeths = helpers.curbufmeths
+local meths = helpers.meths
local insert = helpers.insert
local expect = helpers.expect
local feed = helpers.feed
@@ -45,7 +45,7 @@ describe('legacy perl provider', function()
-- :perldo 1; doesn't change $_,
-- the buffer should not be changed
command('normal :perldo 1;')
- eq(false, curbufmeths.get_option('modified'))
+ eq(false, meths.get_option_value('modified', {}))
-- insert some text
insert('abc\ndef\nghi')
expect([[
diff --git a/test/functional/provider/ruby_spec.lua b/test/functional/provider/ruby_spec.lua
index fba96100fc..d3b967dfbe 100644
--- a/test/functional/provider/ruby_spec.lua
+++ b/test/functional/provider/ruby_spec.lua
@@ -3,7 +3,6 @@ local helpers = require('test.functional.helpers')(after_each)
local assert_alive = helpers.assert_alive
local clear = helpers.clear
local command = helpers.command
-local curbufmeths = helpers.curbufmeths
local eq = helpers.eq
local exc_exec = helpers.exc_exec
local expect = helpers.expect
@@ -98,7 +97,7 @@ describe(':rubydo command', function()
it('does not modify the buffer if no changes are made', function()
command('normal :rubydo 42')
- eq(false, curbufmeths.get_option('modified'))
+ eq(false, meths.get_option_value('modified', {}))
end)
end)
diff --git a/test/functional/shada/buffers_spec.lua b/test/functional/shada/buffers_spec.lua
index 26a4569fce..b1c4ded541 100644
--- a/test/functional/shada/buffers_spec.lua
+++ b/test/functional/shada/buffers_spec.lua
@@ -1,7 +1,7 @@
-- shada buffer list saving/reading support
local helpers = require('test.functional.helpers')(after_each)
-local nvim_command, funcs, eq, curbufmeths =
- helpers.command, helpers.funcs, helpers.eq, helpers.curbufmeths
+local nvim_command, funcs, eq, curbufmeths, meths =
+ helpers.command, helpers.funcs, helpers.eq, helpers.curbufmeths, helpers.meths
local expect_exit = helpers.expect_exit
local shada_helpers = require('test.functional.shada.helpers')
@@ -48,7 +48,7 @@ describe('shada support code', function()
reset('set shada+=%')
nvim_command('edit ' .. testfilename)
nvim_command('edit ' .. testfilename_2)
- curbufmeths.set_option('buflisted', false)
+ meths.set_option_value('buflisted', false, {})
expect_exit(nvim_command, 'qall')
reset('set shada+=%')
eq(2, funcs.bufnr('$'))
@@ -60,7 +60,7 @@ describe('shada support code', function()
reset('set shada+=%')
nvim_command('edit ' .. testfilename)
nvim_command('edit ' .. testfilename_2)
- curbufmeths.set_option('buftype', 'quickfix')
+ meths.set_option_value('buftype', 'quickfix', {})
expect_exit(nvim_command, 'qall')
reset('set shada+=%')
eq(2, funcs.bufnr('$'))
diff --git a/test/functional/shada/history_spec.lua b/test/functional/shada/history_spec.lua
index aa4106ad63..433db3171e 100644
--- a/test/functional/shada/history_spec.lua
+++ b/test/functional/shada/history_spec.lua
@@ -106,13 +106,13 @@ describe('ShaDa support code', function()
end)
it('dumps and loads last search pattern with offset', function()
- meths.set_option('wrapscan', false)
+ meths.set_option_value('wrapscan', false, {})
funcs.setline('.', {'foo', 'bar--'})
nvim_feed('gg0/a/e+1\n')
eq({0, 2, 3, 0}, funcs.getpos('.'))
nvim_command('wshada')
reset()
- meths.set_option('wrapscan', false)
+ meths.set_option_value('wrapscan', false, {})
funcs.setline('.', {'foo', 'bar--'})
nvim_feed('gg0n')
eq({0, 2, 3, 0}, funcs.getpos('.'))
@@ -121,13 +121,13 @@ describe('ShaDa support code', function()
it('dumps and loads last search pattern with offset and backward direction',
function()
- meths.set_option('wrapscan', false)
+ meths.set_option_value('wrapscan', false, {})
funcs.setline('.', {'foo', 'bar--'})
nvim_feed('G$?a?e+1\n')
eq({0, 2, 3, 0}, funcs.getpos('.'))
nvim_command('wshada')
reset()
- meths.set_option('wrapscan', false)
+ meths.set_option_value('wrapscan', false, {})
funcs.setline('.', {'foo', 'bar--'})
nvim_feed('G$n')
eq({0, 2, 3, 0}, funcs.getpos('.'))
diff --git a/test/functional/shada/shada_spec.lua b/test/functional/shada/shada_spec.lua
index cc21d08620..3a3238eb34 100644
--- a/test/functional/shada/shada_spec.lua
+++ b/test/functional/shada/shada_spec.lua
@@ -196,30 +196,30 @@ describe('ShaDa support code', function()
end)
it('is able to set &shada after &viminfo', function()
- meths.set_option('viminfo', '\'10')
- eq('\'10', meths.get_option('viminfo'))
- eq('\'10', meths.get_option('shada'))
- meths.set_option('shada', '')
- eq('', meths.get_option('viminfo'))
- eq('', meths.get_option('shada'))
+ meths.set_option_value('viminfo', '\'10', {})
+ eq('\'10', meths.get_option_value('viminfo', {}))
+ eq('\'10', meths.get_option_value('shada', {}))
+ meths.set_option_value('shada', '', {})
+ eq('', meths.get_option_value('viminfo', {}))
+ eq('', meths.get_option_value('shada', {}))
end)
it('is able to set all& after setting &shada', function()
- meths.set_option('shada', '\'10')
- eq('\'10', meths.get_option('viminfo'))
- eq('\'10', meths.get_option('shada'))
+ meths.set_option_value('shada', '\'10', {})
+ eq('\'10', meths.get_option_value('viminfo', {}))
+ eq('\'10', meths.get_option_value('shada', {}))
nvim_command('set all&')
- eq('!,\'100,<50,s10,h', meths.get_option('viminfo'))
- eq('!,\'100,<50,s10,h', meths.get_option('shada'))
+ eq('!,\'100,<50,s10,h', meths.get_option_value('viminfo', {}))
+ eq('!,\'100,<50,s10,h', meths.get_option_value('shada', {}))
end)
it('is able to set &shada after &viminfo using :set', function()
nvim_command('set viminfo=\'10')
- eq('\'10', meths.get_option('viminfo'))
- eq('\'10', meths.get_option('shada'))
+ eq('\'10', meths.get_option_value('viminfo', {}))
+ eq('\'10', meths.get_option_value('shada', {}))
nvim_command('set shada=')
- eq('', meths.get_option('viminfo'))
- eq('', meths.get_option('shada'))
+ eq('', meths.get_option_value('viminfo', {}))
+ eq('', meths.get_option_value('shada', {}))
end)
it('setting &shada gives proper error message on missing number', function()
@@ -237,12 +237,12 @@ describe('ShaDa support code', function()
funcs.mkdir(dirname, '', 0)
eq(0, funcs.filewritable(dirname))
reset{shadafile=dirshada, args={'--cmd', 'set shada='}}
- meths.set_option('shada', '\'10')
+ meths.set_option_value('shada', '\'10', {})
eq('Vim(wshada):E886: System error while opening ShaDa file '
.. 'Xtest-functional-shada-shada.d/main.shada for reading to merge '
.. 'before writing it: permission denied',
exc_exec('wshada'))
- meths.set_option('shada', '')
+ meths.set_option_value('shada', '', {})
end)
end)
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index b983ea89d5..4ce354b9a9 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -197,7 +197,7 @@ describe(':terminal buffer', function()
it('handles loss of focus gracefully', function()
-- Change the statusline to avoid printing the file name, which varies.
- nvim('set_option', 'statusline', '==========')
+ nvim('set_option_value', 'statusline', '==========', {})
feed_command('set laststatus=0')
-- Save the buffer number of the terminal for later testing.
@@ -281,6 +281,7 @@ describe(':terminal buffer', function()
end)
it('requires bang (!) to close a running job #15402', function()
+ skip(is_os('win'), "Test freezes the CI and makes it time out")
eq('Vim(wqall):E948: Job still running', exc_exec('wqall'))
for _, cmd in ipairs({ 'bdelete', '%bdelete', 'bwipeout', 'bunload' }) do
matches('^Vim%('..cmd:gsub('%%', '')..'%):E89: term://.*tty%-test.* will be killed %(add %! to override%)$',
diff --git a/test/functional/terminal/edit_spec.lua b/test/functional/terminal/edit_spec.lua
index 80287bb3d0..db5dba7374 100644
--- a/test/functional/terminal/edit_spec.lua
+++ b/test/functional/terminal/edit_spec.lua
@@ -21,8 +21,8 @@ describe(':edit term://*', function()
before_each(function()
clear()
- meths.set_option('shell', testprg('shell-test'))
- meths.set_option('shellcmdflag', 'EXE')
+ meths.set_option_value('shell', testprg('shell-test'), {})
+ meths.set_option_value('shellcmdflag', 'EXE', {})
end)
it('runs TermOpen event', function()
@@ -40,7 +40,7 @@ describe(':edit term://*', function()
local columns, lines = 20, 4
local scr = get_screen(columns, lines)
local rep = 97
- meths.set_option('shellcmdflag', 'REP ' .. rep)
+ meths.set_option_value('shellcmdflag', 'REP ' .. rep, {})
command('set shellxquote=') -- win: avoid extra quotes
local sb = 10
command('autocmd TermOpen * :setlocal scrollback='..tostring(sb)
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index 6b7e93a864..28751a3504 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -133,8 +133,8 @@ describe(':terminal (with fake shell)', function()
screen = Screen.new(50, 4)
screen:attach({rgb=false})
-- shell-test.c is a fake shell that prints its arguments and exits.
- nvim('set_option', 'shell', testprg('shell-test'))
- nvim('set_option', 'shellcmdflag', 'EXE')
+ nvim('set_option_value', 'shell', testprg('shell-test'), {})
+ nvim('set_option_value', 'shellcmdflag', 'EXE', {})
end)
-- Invokes `:terminal {cmd}` using a fake shell (shell-test.c) which prints
@@ -157,7 +157,7 @@ describe(':terminal (with fake shell)', function()
end)
it("with no argument, and 'shell' is set to empty string", function()
- nvim('set_option', 'shell', '')
+ nvim('set_option_value', 'shell', '', {})
terminal_with_fake_shell()
screen:expect([[
^ |
@@ -169,7 +169,7 @@ describe(':terminal (with fake shell)', function()
it("with no argument, but 'shell' has arguments, acts like termopen()", function()
skip(is_os('win'))
- nvim('set_option', 'shell', testprg('shell-test')..' -t jeff')
+ nvim('set_option_value', 'shell', testprg('shell-test')..' -t jeff', {})
terminal_with_fake_shell()
screen:expect([[
^jeff $ |
@@ -193,7 +193,7 @@ describe(':terminal (with fake shell)', function()
it("executes a given command through the shell, when 'shell' has arguments", function()
skip(is_os('win'))
- nvim('set_option', 'shell', testprg('shell-test')..' -t jeff')
+ nvim('set_option_value', 'shell', testprg('shell-test')..' -t jeff', {})
command('set shellxquote=') -- win: avoid extra quotes
terminal_with_fake_shell('echo hi')
screen:expect([[
diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua
index ac76217023..a2e9ffa1d7 100644
--- a/test/functional/terminal/mouse_spec.lua
+++ b/test/functional/terminal/mouse_spec.lua
@@ -11,7 +11,7 @@ describe(':terminal mouse', function()
before_each(function()
clear()
- nvim('set_option', 'statusline', '==========')
+ nvim('set_option_value', 'statusline', '==========', {})
command('highlight StatusLine cterm=NONE')
command('highlight StatusLineNC cterm=NONE')
command('highlight VertSplit cterm=NONE')
@@ -352,7 +352,7 @@ describe(':terminal mouse', function()
end)
it('handles terminal size when switching buffers', function()
- nvim('set_option', 'hidden', true)
+ nvim('set_option_value', 'hidden', true, {})
feed('<c-\\><c-n><c-w><c-w>')
screen:expect([[
{7: 27 }line │line30 |
diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua
index 5d967e0340..5d3e55d898 100644
--- a/test/functional/terminal/scrollback_spec.lua
+++ b/test/functional/terminal/scrollback_spec.lua
@@ -8,7 +8,7 @@ local command = helpers.command
local matches = helpers.matches
local poke_eventloop = helpers.poke_eventloop
local retry = helpers.retry
-local curbufmeths = helpers.curbufmeths
+local meths = helpers.meths
local nvim = helpers.nvim
local feed_data = thelpers.feed_data
local pcall_err = helpers.pcall_err
@@ -381,8 +381,8 @@ describe("'scrollback' option", function()
local function set_fake_shell()
-- shell-test.c is a fake shell that prints its arguments and exits.
- nvim('set_option', 'shell', testprg('shell-test'))
- nvim('set_option', 'shellcmdflag', 'EXE')
+ nvim('set_option_value', 'shell', testprg('shell-test'), {})
+ nvim('set_option_value', 'shellcmdflag', 'EXE', {})
end
local function expect_lines(expected, epsilon)
@@ -401,7 +401,7 @@ describe("'scrollback' option", function()
screen = thelpers.screen_setup(nil, "['sh']", 30)
end
- curbufmeths.set_option('scrollback', 0)
+ meths.set_option_value('scrollback', 0, {})
feed_data(('%s REP 31 line%s'):format(testprg('shell-test'), is_os('win') and '\r' or '\n'))
screen:expect{any='30: line '}
retry(nil, nil, function() expect_lines(7) end)
@@ -417,7 +417,7 @@ describe("'scrollback' option", function()
screen = thelpers.screen_setup(nil, "['sh']", 30)
end
- curbufmeths.set_option('scrollback', 200)
+ meths.set_option_value('scrollback', 200, {})
-- Wait for prompt.
screen:expect{any='%$'}
@@ -426,10 +426,10 @@ describe("'scrollback' option", function()
screen:expect{any='30: line '}
retry(nil, nil, function() expect_lines(33, 2) end)
- curbufmeths.set_option('scrollback', 10)
+ meths.set_option_value('scrollback', 10, {})
poke_eventloop()
retry(nil, nil, function() expect_lines(16) end)
- curbufmeths.set_option('scrollback', 10000)
+ meths.set_option_value('scrollback', 10000, {})
retry(nil, nil, function() expect_lines(16) end)
-- Terminal job data is received asynchronously, may happen before the
-- 'scrollback' option is synchronized with the internal sb_buffer.
@@ -484,18 +484,18 @@ describe("'scrollback' option", function()
]])
local term_height = 6 -- Actual terminal screen height, not the scrollback
-- Initial
- local scrollback = curbufmeths.get_option('scrollback')
+ local scrollback = meths.get_option_value('scrollback', {})
eq(scrollback + term_height, eval('line("$")'))
-- Reduction
scrollback = scrollback - 2
- curbufmeths.set_option('scrollback', scrollback)
+ meths.set_option_value('scrollback', scrollback, {})
eq(scrollback + term_height, eval('line("$")'))
end)
it('defaults to 10000 in :terminal buffers', function()
set_fake_shell()
command('terminal')
- eq(10000, curbufmeths.get_option('scrollback'))
+ eq(10000, meths.get_option_value('scrollback', {}))
end)
it('error if set to invalid value', function()
@@ -507,7 +507,7 @@ describe("'scrollback' option", function()
it('defaults to -1 on normal buffers', function()
command('new')
- eq(-1, curbufmeths.get_option('scrollback'))
+ eq(-1, meths.get_option_value('scrollback', {}))
end)
it(':setlocal in a :terminal buffer', function()
@@ -516,45 +516,45 @@ describe("'scrollback' option", function()
-- _Global_ scrollback=-1 defaults :terminal to 10_000.
command('setglobal scrollback=-1')
command('terminal')
- eq(10000, curbufmeths.get_option('scrollback'))
+ eq(10000, meths.get_option_value('scrollback', {}))
-- _Local_ scrollback=-1 in :terminal forces the _maximum_.
command('setlocal scrollback=-1')
retry(nil, nil, function() -- Fixup happens on refresh, not immediately.
- eq(100000, curbufmeths.get_option('scrollback'))
+ eq(100000, meths.get_option_value('scrollback', {}))
end)
-- _Local_ scrollback=-1 during TermOpen forces the maximum. #9605
command('setglobal scrollback=-1')
command('autocmd TermOpen * setlocal scrollback=-1')
command('terminal')
- eq(100000, curbufmeths.get_option('scrollback'))
+ eq(100000, meths.get_option_value('scrollback', {}))
end)
it(':setlocal in a normal buffer', function()
command('new')
-- :setlocal to -1.
command('setlocal scrollback=-1')
- eq(-1, curbufmeths.get_option('scrollback'))
+ eq(-1, meths.get_option_value('scrollback', {}))
-- :setlocal to anything except -1. Currently, this just has no effect.
command('setlocal scrollback=42')
- eq(42, curbufmeths.get_option('scrollback'))
+ eq(42, meths.get_option_value('scrollback', {}))
end)
it(':set updates local value and global default', function()
set_fake_shell()
command('set scrollback=42') -- set global value
- eq(42, curbufmeths.get_option('scrollback'))
+ eq(42, meths.get_option_value('scrollback', {}))
command('terminal')
- eq(42, curbufmeths.get_option('scrollback')) -- inherits global default
+ eq(42, meths.get_option_value('scrollback', {})) -- inherits global default
command('setlocal scrollback=99')
- eq(99, curbufmeths.get_option('scrollback'))
+ eq(99, meths.get_option_value('scrollback', {}))
command('set scrollback<') -- reset to global default
- eq(42, curbufmeths.get_option('scrollback'))
+ eq(42, meths.get_option_value('scrollback', {}))
command('setglobal scrollback=734') -- new global default
- eq(42, curbufmeths.get_option('scrollback')) -- local value did not change
+ eq(42, meths.get_option_value('scrollback', {})) -- local value did not change
command('terminal')
- eq(734, curbufmeths.get_option('scrollback'))
+ eq(734, meths.get_option_value('scrollback', {}))
end)
end)
@@ -578,7 +578,7 @@ describe("pending scrollback line handling", function()
local api = vim.api
local buf = api.nvim_create_buf(true, true)
local chan = api.nvim_open_term(buf, {})
- api.nvim_win_set_option(0, "number", true)
+ vim.wo.number = true
api.nvim_chan_send(chan, ("a\n"):rep(11) .. "a")
api.nvim_win_set_buf(0, buf)
]]
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index b69867af89..1b65c1cddc 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -112,7 +112,7 @@ describe('TUI', function()
child_session:request("nvim_exec", [[
set more
func! ManyErr()
- for i in range(10)
+ for i in range(20)
echoerr "FAIL ".i
endfor
endfunc
@@ -128,7 +128,35 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]]}
- feed_data('d')
+ screen:try_resize(50,10)
+ screen:expect{grid=[[
+ :call ManyErr() |
+ {8:Error detected while processing function ManyErr:} |
+ {11:line 2:} |
+ {8:FAIL 0} |
+ {8:FAIL 1} |
+ {8:FAIL 2} |
+ |
+ |
+ {10:-- More --}{1: } |
+ {3:-- TERMINAL --} |
+ ]]}
+
+ feed_data('j')
+ screen:expect{grid=[[
+ {8:Error detected while processing function ManyErr:} |
+ {11:line 2:} |
+ {8:FAIL 0} |
+ {8:FAIL 1} |
+ {8:FAIL 2} |
+ {8:FAIL 3} |
+ {8:FAIL 4} |
+ {8:FAIL 5} |
+ {10:-- More --}{1: } |
+ {3:-- TERMINAL --} |
+ ]]}
+
+ screen:try_resize(50,7)
screen:expect{grid=[[
{8:FAIL 1} |
{8:FAIL 2} |
@@ -1430,9 +1458,9 @@ describe('TUI', function()
it('allows grid to assume wider ambiguous-width characters than host terminal #19686', function()
child_session:request('nvim_buf_set_lines', 0, 0, -1, true, { ('℃'):rep(60), ('℃'):rep(60) })
- child_session:request('nvim_win_set_option', 0, 'cursorline', true)
- child_session:request('nvim_win_set_option', 0, 'list', true)
- child_session:request('nvim_win_set_option', 0, 'listchars', 'eol:$')
+ child_session:request('nvim_set_option_value', 'cursorline', true, {})
+ child_session:request('nvim_set_option_value', 'list', true, {})
+ child_session:request('nvim_set_option_value', 'listchars', 'eol:$', {win=0})
feed_data('gg')
local singlewidth_screen = [[
{13:℃}{12:℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃}|
@@ -1455,9 +1483,9 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]]
screen:expect(singlewidth_screen)
- child_session:request('nvim_set_option', 'ambiwidth', 'double')
+ child_session:request('nvim_set_option_value', 'ambiwidth', 'double', {})
screen:expect(doublewidth_screen)
- child_session:request('nvim_set_option', 'ambiwidth', 'single')
+ child_session:request('nvim_set_option_value', 'ambiwidth', 'single', {})
screen:expect(singlewidth_screen)
child_session:request('nvim_call_function', 'setcellwidths', {{{0x2103, 0x2103, 2}}})
screen:expect(doublewidth_screen)
diff --git a/test/functional/terminal/window_spec.lua b/test/functional/terminal/window_spec.lua
index 80e9d78400..f90e4f7e9d 100644
--- a/test/functional/terminal/window_spec.lua
+++ b/test/functional/terminal/window_spec.lua
@@ -64,7 +64,7 @@ describe(':terminal window', function()
{7: 1 }tty ready |
{7: 2 }rows: 6, cols: 48 |
{7: 3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO|
- {7: 4 }WXYZrows: 6, cols: 41 |
+ {7: 4 }PQRSTUVWXYZrows: 6, cols: 41 |
{7: 5 }{1: } |
{7: 6 } |
{3:-- TERMINAL --} |
@@ -74,7 +74,7 @@ describe(':terminal window', function()
{7: 1 }tty ready |
{7: 2 }rows: 6, cols: 48 |
{7: 3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO|
- {7: 4 }WXYZrows: 6, cols: 41 |
+ {7: 4 }PQRSTUVWXYZrows: 6, cols: 41 |
{7: 5 } abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN|
{7: 6 }OPQRSTUVWXYZ{1: } |
{3:-- TERMINAL --} |
diff --git a/test/functional/terminal/window_split_tab_spec.lua b/test/functional/terminal/window_split_tab_spec.lua
index 1d77e1e92e..da14531fa2 100644
--- a/test/functional/terminal/window_split_tab_spec.lua
+++ b/test/functional/terminal/window_split_tab_spec.lua
@@ -19,7 +19,7 @@ describe(':terminal', function()
clear()
-- set the statusline to a constant value because of variables like pid
-- and current directory and to improve visibility of splits
- meths.set_option('statusline', '==========')
+ meths.set_option_value('statusline', '==========', {})
command('highlight StatusLine cterm=NONE')
command('highlight StatusLineNC cterm=NONE')
command('highlight VertSplit cterm=NONE')
@@ -71,7 +71,7 @@ describe(':terminal', function()
end)
it('does not change size if updated when not visible in any window #19665', function()
- local channel = meths.buf_get_option(0, 'channel')
+ local channel = meths.get_option_value('channel', {})
command('enew')
sleep(100)
meths.chan_send(channel, 'foo')
diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua
index 9afce0b3a0..14de07639b 100644
--- a/test/functional/treesitter/parser_spec.lua
+++ b/test/functional/treesitter/parser_spec.lua
@@ -483,10 +483,9 @@ end]]
return list
]]
- eq({ 'any-of?', 'contains?', 'eq?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list)
+ eq({ 'any-of?', 'contains?', 'eq?', 'has-ancestor?', 'has-parent?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list)
end)
-
it('allows to set simple ranges', function()
insert(test_text)
@@ -528,6 +527,7 @@ end]]
eq(range_tbl, { { { 0, 0, 0, 17, 1, 508 } } })
end)
+
it("allows to set complex ranges", function()
insert(test_text)
@@ -992,4 +992,58 @@ int x = INT_MAX;
}, run_query())
end)
+
+ it('handles ranges when source is a multiline string (#20419)', function()
+ local source = [==[
+ vim.cmd[[
+ set number
+ set cmdheight=2
+ set lastsatus=2
+ ]]
+
+ set query = [[;; query
+ ((function_call
+ name: [
+ (identifier) @_cdef_identifier
+ (_ _ (identifier) @_cdef_identifier)
+ ]
+ arguments: (arguments (string content: _ @injection.content)))
+ (#set! injection.language "c")
+ (#eq? @_cdef_identifier "cdef"))
+ ]]
+ ]==]
+
+ local r = exec_lua([[
+ local parser = vim.treesitter.get_string_parser(..., 'lua')
+ parser:parse()
+ local ranges = {}
+ parser:for_each_tree(function(tstree, tree)
+ ranges[tree:lang()] = { tstree:root():range(true) }
+ end)
+ return ranges
+ ]], source)
+
+ eq({
+ lua = { 0, 6, 6, 16, 4, 438 },
+ query = { 6, 20, 113, 15, 6, 431 },
+ vim = { 1, 0, 16, 4, 6, 89 }
+ }, r)
+
+ -- The above ranges are provided directly from treesitter, however query directives may mutate
+ -- the ranges but only provide a Range4. Strip the byte entries from the ranges and make sure
+ -- add_bytes() produces the same result.
+
+ local rb = exec_lua([[
+ local r, source = ...
+ local add_bytes = require('vim.treesitter._range').add_bytes
+ for lang, range in pairs(r) do
+ r[lang] = {range[1], range[2], range[4], range[5]}
+ r[lang] = add_bytes(source, r[lang])
+ end
+ return r
+ ]], r, source)
+
+ eq(rb, r)
+
+ end)
end)
diff --git a/test/functional/ui/cmdline_highlight_spec.lua b/test/functional/ui/cmdline_highlight_spec.lua
index 636f571641..17e6855ee4 100644
--- a/test/functional/ui/cmdline_highlight_spec.lua
+++ b/test/functional/ui/cmdline_highlight_spec.lua
@@ -178,7 +178,7 @@ end
describe('Command-line coloring', function()
it('works', function()
set_color_cb('RainBowParens')
- meths.set_option('more', false)
+ meths.set_option_value('more', false, {})
start_prompt()
screen:expect([[
|
diff --git a/test/functional/ui/cursor_spec.lua b/test/functional/ui/cursor_spec.lua
index 7e28caea04..01475a189d 100644
--- a/test/functional/ui/cursor_spec.lua
+++ b/test/functional/ui/cursor_spec.lua
@@ -265,8 +265,8 @@ describe('ui/cursor', function()
}
-- Another cursor style.
- meths.set_option('guicursor', 'n-v-c:ver35-blinkwait171-blinkoff172-blinkon173'
- ..',ve:hor35,o:ver50,i-ci:block,r-cr:hor90,sm:ver42')
+ meths.set_option_value('guicursor', 'n-v-c:ver35-blinkwait171-blinkoff172-blinkon173'
+ ..',ve:hor35,o:ver50,i-ci:block,r-cr:hor90,sm:ver42', {})
screen:expect(function()
local named = {}
for _, m in ipairs(screen._mode_info) do
@@ -288,7 +288,7 @@ describe('ui/cursor', function()
end)
-- If there is no setting for guicursor, it becomes the default setting.
- meths.set_option('guicursor', 'n:ver35-blinkwait171-blinkoff172-blinkon173-Cursor/lCursor')
+ meths.set_option_value('guicursor', 'n:ver35-blinkwait171-blinkoff172-blinkon173-Cursor/lCursor', {})
screen:expect(function()
for _,m in ipairs(screen._mode_info) do
if m.name ~= 'normal' then
@@ -304,7 +304,7 @@ describe('ui/cursor', function()
end)
it("empty 'guicursor' sets cursor_shape=block in all modes", function()
- meths.set_option('guicursor', '')
+ meths.set_option_value('guicursor', '', {})
screen:expect(function()
-- Empty 'guicursor' sets enabled=false.
eq(false, screen._cursor_style_enabled)
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index f531878bc6..767ec54a7b 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -10,6 +10,7 @@ local expect_events = helpers.expect_events
local meths = helpers.meths
local curbufmeths = helpers.curbufmeths
local command = helpers.command
+local assert_alive = helpers.assert_alive
describe('decorations providers', function()
local screen
@@ -80,7 +81,7 @@ describe('decorations providers', function()
local ns2 = api.nvim_create_namespace "ns2"
api.nvim_set_decoration_provider(ns2, {})
]])
- helpers.assert_alive()
+ assert_alive()
end)
it('leave a trace', function()
@@ -611,6 +612,20 @@ describe('decorations providers', function()
end)
end)
+local example_text = [[
+for _,item in ipairs(items) do
+ local text, hl_id_cell, count = unpack(item)
+ if hl_id_cell ~= nil then
+ hl_id = hl_id_cell
+ end
+ for _ = 1, (count or 1) do
+ local cell = line[colpos]
+ cell.text = text
+ cell.hl_id = hl_id
+ colpos = colpos+1
+ end
+end]]
+
describe('extmark decorations', function()
local screen, ns
before_each( function()
@@ -650,20 +665,6 @@ describe('extmark decorations', function()
ns = meths.create_namespace 'test'
end)
- local example_text = [[
-for _,item in ipairs(items) do
- local text, hl_id_cell, count = unpack(item)
- if hl_id_cell ~= nil then
- hl_id = hl_id_cell
- end
- for _ = 1, (count or 1) do
- local cell = line[colpos]
- cell.text = text
- cell.hl_id = hl_id
- colpos = colpos+1
- end
-end]]
-
it('empty virtual text at eol should not break colorcolumn #17860', function()
insert(example_text)
feed('gg')
@@ -704,14 +705,14 @@ end]]
-- can "float" beyond end of line
meths.buf_set_extmark(0, ns, 5, 28, { virt_text={{'loopy', 'ErrorMsg'}}, virt_text_pos='overlay'})
-- bound check: right edge of window
- meths.buf_set_extmark(0, ns, 2, 26, { virt_text={{'bork bork bork '}, {'bork bork bork', 'ErrorMsg'}}, virt_text_pos='overlay'})
+ meths.buf_set_extmark(0, ns, 2, 26, { virt_text={{'bork bork bork'}, {(' bork'):rep(10), 'ErrorMsg'}}, virt_text_pos='overlay'})
-- empty virt_text should not change anything
meths.buf_set_extmark(0, ns, 6, 16, { virt_text={{''}}, virt_text_pos='overlay'})
screen:expect{grid=[[
^for _,item in ipairs(items) do |
{2:|} local text, hl_id_cell, count = unpack(item) |
- {2:|} if hl_id_cell ~= nil tbork bork bork {4:bork bork}|
+ {2:|} if hl_id_cell ~= nil tbork bork bork{4: bork bork}|
{2:|} {1:|} hl_id = hl_id_cell |
{2:|} end |
{2:|} for _ = 1, (count or 1) {4:loopy} |
@@ -726,7 +727,6 @@ end]]
|
]]}
-
-- handles broken lines
screen:try_resize(22, 25)
screen:expect{grid=[[
@@ -736,7 +736,7 @@ end]]
cell, count = unpack(i|
tem) |
{2:|} if hl_id_cell ~= n|
- il tbork bork bork {4:bor}|
+ il tbork bork bork{4: bor}|
{2:|} {1:|} hl_id = hl_id_|
cell |
{2:|} end |
@@ -756,6 +756,95 @@ end]]
{1:~ }|
|
]]}
+
+ -- truncating in the middle of a char leaves a space
+ meths.buf_set_lines(0, 0, 1, true, {'for _,item in ipairs(items) do -- 古古古'})
+ meths.buf_set_lines(0, 10, 12, true, {' end -- ??????????', 'end -- ?古古古古?古古'})
+ meths.buf_set_extmark(0, ns, 0, 35, { virt_text={{'A', 'ErrorMsg'}, {'AA'}}, virt_text_pos='overlay'})
+ meths.buf_set_extmark(0, ns, 10, 19, { virt_text={{'口口口', 'ErrorMsg'}}, virt_text_pos='overlay'})
+ meths.buf_set_extmark(0, ns, 11, 21, { virt_text={{'口口口', 'ErrorMsg'}}, virt_text_pos='overlay'})
+ meths.buf_set_extmark(0, ns, 11, 8, { virt_text={{'口口', 'ErrorMsg'}}, virt_text_pos='overlay'})
+ screen:expect{grid=[[
+ ^for _,item in ipairs(i|
+ tems) do -- {4:A}AA 古 |
+ {2:|} local text, hl_id_|
+ cell, count = unpack(i|
+ tem) |
+ {2:|} if hl_id_cell ~= n|
+ il tbork bork bork{4: bor}|
+ {2:|} {1:|} hl_id = hl_id_|
+ cell |
+ {2:|} end |
+ {2:|} for _ = 1, (count |
+ or 1) {4:loopy} |
+ {2:|} {1:|} local cell = l|
+ ine[colpos] |
+ {2:|} {1:|} cell.text = te|
+ xt |
+ {2:|} {1:|} cell.hl_id = h|
+ l_id |
+ {2:|} {1:|} cofoo{3:bar}{4:!!}olpo|
+ s+1 |
+ end -- ???????{4:口 }|
+ end -- {4:口口} 古古{4:口口 }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ screen:try_resize(82, 13)
+ screen:expect{grid=[[
+ ^for _,item in ipairs(items) do -- {4:A}AA 古 |
+ {2:|} local text, hl_id_cell, count = unpack(item) |
+ {2:|} if hl_id_cell ~= nil tbork bork bork{4: bork bork bork bork bork bork bork bork b}|
+ {2:|} {1:|} hl_id = hl_id_cell |
+ {2:|} end |
+ {2:|} for _ = 1, (count or 1) {4:loopy} |
+ {2:|} {1:|} local cell = line[colpos] |
+ {2:|} {1:|} cell.text = text |
+ {2:|} {1:|} cell.hl_id = hl_id |
+ {2:|} {1:|} cofoo{3:bar}{4:!!}olpos+1 |
+ end -- ???????{4:口口口} |
+ end -- {4:口口} 古古{4:口口口} |
+ |
+ ]]}
+
+ meths.buf_clear_namespace(0, ns, 0, -1)
+ screen:expect{grid=[[
+ ^for _,item in ipairs(items) do -- 古古古 |
+ local text, hl_id_cell, count = unpack(item) |
+ if hl_id_cell ~= nil then |
+ hl_id = hl_id_cell |
+ end |
+ for _ = 1, (count or 1) do |
+ local cell = line[colpos] |
+ cell.text = text |
+ cell.hl_id = hl_id |
+ colpos = colpos+1 |
+ end -- ?????????? |
+ end -- ?古古古古?古古 |
+ |
+ ]]}
+
+ screen:try_resize(50, 2)
+ command('set nowrap')
+ meths.buf_set_lines(0, 12, 12, true, {'-- ' .. ('…'):rep(57)})
+ feed('G')
+ meths.buf_set_extmark(0, ns, 12, 123, { virt_text={{'!!!!!', 'ErrorMsg'}}, virt_text_pos='overlay', virt_text_hide=true})
+ screen:expect{grid=[[
+ ^-- …………………………………………………………………………………………………………{4:!!!!!}……|
+ |
+ ]]}
+ feed('40zl')
+ screen:expect{grid=[[
+ ^………{4:!!!!!}……………………………… |
+ |
+ ]]}
+ feed('10zl')
+ screen:expect{grid=[[
+ ^………………………… |
+ |
+ ]]}
end)
it('can have virtual text of overlay position and styling', function()
@@ -1024,7 +1113,7 @@ end]]
{1:~ }|
|
]]}
- helpers.assert_alive()
+ assert_alive()
end)
it('conceal #19007', function()
@@ -1165,7 +1254,778 @@ end]]
meths.buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestBold', priority = 20 })
screen:expect_unchanged(true)
end)
+end)
+
+
+describe('decorations: inline virtual text', function()
+ local screen, ns
+ before_each( function()
+ clear()
+ screen = Screen.new(50, 10)
+ screen:attach()
+ screen:set_default_attr_ids {
+ [1] = {bold=true, foreground=Screen.colors.Blue};
+ [2] = {foreground = Screen.colors.Brown};
+ [3] = {bold = true, foreground = Screen.colors.SeaGreen};
+ [4] = {background = Screen.colors.Red1, foreground = Screen.colors.Gray100};
+ [5] = {background = Screen.colors.Red1, bold = true};
+ [6] = {foreground = Screen.colors.DarkCyan};
+ [7] = {background = Screen.colors.LightGrey};
+ [8] = {bold = true};
+ [9] = {background = Screen.colors.Plum1};
+ [10] = {foreground = Screen.colors.SlateBlue};
+ [11] = {blend = 30, background = Screen.colors.Red1};
+ [12] = {background = Screen.colors.Yellow1};
+ [13] = {reverse = true};
+ [14] = {foreground = Screen.colors.SlateBlue, background = Screen.colors.LightMagenta};
+ [15] = {bold = true, reverse = true};
+ [16] = {foreground = Screen.colors.Red};
+ [17] = {background = Screen.colors.LightGrey, foreground = Screen.colors.DarkBlue};
+ [18] = {background = Screen.colors.LightGrey, foreground = Screen.colors.Red};
+ }
+
+ ns = meths.create_namespace 'test'
+ end)
+
+
+ it('works', function()
+ insert(example_text)
+ feed 'gg'
+ screen:expect{grid=[[
+ ^for _,item in ipairs(items) do |
+ local text, hl_id_cell, count = unpack(item) |
+ if hl_id_cell ~= nil then |
+ hl_id = hl_id_cell |
+ end |
+ for _ = 1, (count or 1) do |
+ local cell = line[colpos] |
+ cell.text = text |
+ cell.hl_id = hl_id |
+ |
+ ]]}
+
+ meths.buf_set_extmark(0, ns, 1, 14, {virt_text={{': ', 'Special'}, {'string', 'Type'}}, virt_text_pos='inline'})
+ screen:expect{grid=[[
+ ^for _,item in ipairs(items) do |
+ local text{10:: }{3:string}, hl_id_cell, count = unpack|
+ (item) |
+ if hl_id_cell ~= nil then |
+ hl_id = hl_id_cell |
+ end |
+ for _ = 1, (count or 1) do |
+ local cell = line[colpos] |
+ cell.text = text |
+ |
+ ]]}
+
+ screen:try_resize(55, 10)
+ screen:expect{grid=[[
+ ^for _,item in ipairs(items) do |
+ local text{10:: }{3:string}, hl_id_cell, count = unpack(item|
+ ) |
+ if hl_id_cell ~= nil then |
+ hl_id = hl_id_cell |
+ end |
+ for _ = 1, (count or 1) do |
+ local cell = line[colpos] |
+ cell.text = text |
+ |
+ ]]}
+
+ screen:try_resize(56, 10)
+ screen:expect{grid=[[
+ ^for _,item in ipairs(items) do |
+ local text{10:: }{3:string}, hl_id_cell, count = unpack(item)|
+ if hl_id_cell ~= nil then |
+ hl_id = hl_id_cell |
+ end |
+ for _ = 1, (count or 1) do |
+ local cell = line[colpos] |
+ cell.text = text |
+ cell.hl_id = hl_id |
+ |
+ ]]}
+ end)
+
+ it('cursor positions are correct with multiple inline virtual text', function()
+ insert('12345678')
+ meths.buf_set_extmark(0, ns, 0, 4,
+ { virt_text = { { ' virtual text ', 'Special' } }, virt_text_pos = 'inline' })
+ meths.buf_set_extmark(0, ns, 0, 4,
+ { virt_text = { { ' virtual text ', 'Special' } }, virt_text_pos = 'inline' })
+ feed '^'
+ feed '4l'
+ screen:expect { grid = [[
+ 1234{10: virtual text virtual text }^5678 |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('adjusts cursor location correctly when inserting around inline virtual text', function()
+ insert('12345678')
+ feed '$'
+ meths.buf_set_extmark(0, ns, 0, 4,
+ { virt_text = { { ' virtual text ', 'Special' } }, virt_text_pos = 'inline' })
+
+ screen:expect { grid = [[
+ 1234{10: virtual text }567^8 |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('has correct highlighting with multi-byte characters', function()
+ insert('12345678')
+ meths.buf_set_extmark(0, ns, 0, 4,
+ { virt_text = { { 'múlti-byté chñröcters 修补', 'Special' } }, virt_text_pos = 'inline' })
+ screen:expect { grid = [[
+ 1234{10:múlti-byté chñröcters 修补}567^8 |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('has correct cursor position when inserting around virtual text', function()
+ insert('12345678')
+ meths.buf_set_extmark(0, ns, 0, 4,
+ { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
+ feed '^'
+ feed '3l'
+ feed 'a'
+ screen:expect { grid = [[
+ 1234{10:^virtual text}5678 |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {8:-- INSERT --} |
+ ]]}
+ feed '<ESC>'
+ screen:expect{grid=[[
+ 123^4{10:virtual text}5678 |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ feed '^'
+ feed '4l'
+ feed 'i'
+ screen:expect { grid = [[
+ 1234{10:^virtual text}5678 |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {8:-- INSERT --} |
+ ]]}
+ end)
+
+ it('has correct cursor position with virtual text on an empty line', function()
+ meths.buf_set_extmark(0, ns, 0, 0,
+ { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
+ screen:expect { grid = [[
+ {10:^virtual text} |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('text is drawn correctly when inserting a wrapping virtual text on an empty line', function()
+ feed('o<esc>')
+ insert([[aaaaaaa
+
+bbbbbbb]])
+ meths.buf_set_extmark(0, ns, 0, 0,
+ { virt_text = { { string.rep('X', 51), 'Special' } }, virt_text_pos = 'inline' })
+ meths.buf_set_extmark(0, ns, 2, 0,
+ { virt_text = { { string.rep('X', 50), 'Special' } }, virt_text_pos = 'inline' })
+ feed('gg0')
+ screen:expect { grid = [[
+ {10:^XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
+ {10:X} |
+ aaaaaaa |
+ {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
+ bbbbbbb |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed('j')
+ screen:expect { grid = [[
+ {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
+ {10:X} |
+ ^aaaaaaa |
+ {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
+ bbbbbbb |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed('j')
+ screen:expect { grid = [[
+ {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
+ {10:X} |
+ aaaaaaa |
+ {10:^XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
+ bbbbbbb |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed('j')
+ screen:expect { grid = [[
+ {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
+ {10:X} |
+ aaaaaaa |
+ {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
+ ^bbbbbbb |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('cursor position is correct with virtual text attached to hard tabs', function()
+ command('set noexpandtab')
+ feed('i')
+ feed('<TAB>')
+ feed('<TAB>')
+ feed('test')
+ feed('<ESC>')
+ meths.buf_set_extmark(0, ns, 0, 1,
+ { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
+ feed('0')
+ screen:expect { grid = [[
+ ^ {10:virtual text} test |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed('l')
+ screen:expect { grid = [[
+ {10:virtual text} ^ test |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed('l')
+ screen:expect { grid = [[
+ {10:virtual text} ^test |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed('l')
+ screen:expect { grid = [[
+ {10:virtual text} t^est |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed('l')
+ screen:expect { grid = [[
+ {10:virtual text} te^st |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('cursor position is correct with virtual text on an empty line', function()
+ command('set linebreak')
+ insert('one twoword')
+ feed('0')
+ meths.buf_set_extmark(0, ns, 0, 3,
+ { virt_text = { { ': virtual text', 'Special' } }, virt_text_pos = 'inline' })
+ screen:expect { grid = [[
+ ^one{10:: virtual text} twoword |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('search highlight is correct', function()
+ insert('foo foo foo foo')
+ feed('0')
+ meths.buf_set_extmark(0, ns, 0, 8,
+ { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
+ screen:expect { grid = [[
+ ^foo foo {10:virtual text}foo foo |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed('/foo')
+ screen:expect { grid = [[
+ {12:foo} {13:foo} {10:virtual text}{12:foo} {12:foo} |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ /foo^ |
+ ]]}
+ end)
+
+ it('visual select highlight is correct', function()
+ insert('foo foo foo foo')
+ feed('0')
+ meths.buf_set_extmark(0, ns, 0, 8,
+ { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
+ feed('8l')
+ screen:expect { grid = [[
+ foo foo {10:virtual text}^foo foo |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed('v')
+ feed('2h')
+ screen:expect { grid = [[
+ foo fo^o{7: }{10:virtual text}{7:f}oo foo |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {8:-- VISUAL --} |
+ ]]}
+ end)
+
+ it('cursor position is correct when inserting around a virtual text with right gravity set to false', function()
+ insert('foo foo foo foo')
+ meths.buf_set_extmark(0, ns, 0, 8,
+ { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline', right_gravity = false })
+ feed('0')
+ feed('8l')
+ screen:expect { grid = [[
+ foo foo {10:virtual text}^foo foo |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed('i')
+ screen:expect { grid = [[
+ foo foo {10:virtual text}^foo foo |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {8:-- INSERT --} |
+ ]]}
+ end)
+
+ it('cursor position is correct when inserting around virtual texts with both left and right gravity ', function()
+ insert('foo foo foo foo')
+ meths.buf_set_extmark(0, ns, 0, 8, { virt_text = {{ '>>', 'Special' }}, virt_text_pos = 'inline', right_gravity = false })
+ meths.buf_set_extmark(0, ns, 0, 8, { virt_text = {{ '<<', 'Special' }}, virt_text_pos = 'inline', right_gravity = true })
+ feed('08l')
+ screen:expect{ grid = [[
+ foo foo {10:>><<}^foo foo |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed('i')
+ screen:expect { grid = [[
+ foo foo {10:>>^<<}foo foo |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {8:-- INSERT --} |
+ ]]}
+ end)
+
+ it('draws correctly with no wrap multiple virtual text, where one is hidden', function()
+ insert('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz')
+ command("set nowrap")
+ meths.buf_set_extmark(0, ns, 0, 50,
+ { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
+ meths.buf_set_extmark(0, ns, 0, 2,
+ { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
+ feed('$')
+ screen:expect { grid = [[
+ opqrstuvwxyzabcdefghijklmnopqrstuvwx{10:virtual text}y^z|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('draws correctly with no wrap and a long virtual text', function()
+ insert('abcdefghi')
+ command("set nowrap")
+ meths.buf_set_extmark(0, ns, 0, 2,
+ { virt_text = { { string.rep('X', 55), 'Special' } }, virt_text_pos = 'inline' })
+ feed('$')
+ screen:expect { grid = [[
+ {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}cdefgh^i|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('tabs are the correct length with no wrap following virtual text', function()
+ command('set nowrap')
+ feed('itest<TAB>a<ESC>')
+ meths.buf_set_extmark(0, ns, 0, 0,
+ { virt_text = { { string.rep('a', 55), 'Special' } }, virt_text_pos = 'inline' })
+ feed('gg$')
+ screen:expect { grid = [[
+ {10:aaaaaaaaaaaaaaaaaaaaaaaaa}test ^a |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('highlighting does not extend when no wrap is enabled with a long virtual text', function()
+ insert('abcdef')
+ command("set nowrap")
+ meths.buf_set_extmark(0, ns, 0, 3,
+ { virt_text = { { string.rep('X', 50), 'Special' } }, virt_text_pos = 'inline' })
+ feed('$')
+ screen:expect { grid = [[
+ {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}de^f|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('highlighting is correct when virtual text wraps with number', function()
+ insert([[
+ test
+ test]])
+ command('set number')
+ meths.buf_set_extmark(0, ns, 0, 1,
+ { virt_text = { { string.rep('X', 55), 'Special' } }, virt_text_pos = 'inline' })
+ feed('gg0')
+ screen:expect { grid = [[
+ {2: 1 }^t{10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
+ {2: }{10:XXXXXXXXXX}est |
+ {2: 2 }test |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('highlighting is correct when virtual text is proceeded with a match', function()
+ insert([[test]])
+ meths.buf_set_extmark(0, ns, 0, 2,
+ { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
+ feed('gg0')
+ command('match ErrorMsg /e/')
+ screen:expect { grid = [[
+ ^t{4:e}{10:virtual text}st |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ command('match ErrorMsg /s/')
+ screen:expect { grid = [[
+ ^te{10:virtual text}{4:s}t |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('in diff mode is highlighted correct', function()
+ insert([[
+ 9000
+ 0009
+ 0009
+ 9000
+ 0009
+ ]])
+ command("set diff")
+ meths.buf_set_extmark(0, ns, 0, 1,
+ { virt_text = { { 'test', 'Special' } }, virt_text_pos = 'inline', right_gravity = false })
+ command("vnew")
+ insert([[
+ 000
+ 000
+ 000
+ 000
+ 000
+ ]])
+ command("set diff")
+ feed('gg0')
+ screen:expect { grid = [[
+ {9:^000 }│{5:9}{14:test}{9:000 }|
+ {9:000 }│{9:000}{5:9}{9: }|
+ {9:000 }│{9:000}{5:9}{9: }|
+ {9:000 }│{5:9}{9:000 }|
+ {9:000 }│{9:000}{5:9}{9: }|
+ │ |
+ {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|
+ {15:[No Name] [+] }{13:[No Name] [+] }|
+ |
+ ]]}
+ end)
+
+ it('correctly draws when there are multiple overlapping virtual texts on the same line with nowrap', function()
+ command('set nowrap')
+ insert('a')
+ meths.buf_set_extmark(0, ns, 0, 0,
+ { virt_text = { { string.rep('a', 55), 'Special' } }, virt_text_pos = 'inline' })
+ meths.buf_set_extmark(0, ns, 0, 0,
+ { virt_text = { { string.rep('b', 55), 'Special' } }, virt_text_pos = 'inline' })
+ feed('$')
+ screen:expect { grid = [[
+ {10:bbbbbbbbbbbbbbbbbbbbbbbbb}^a |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('correctly draws when overflowing virtual text is followed by tab with no wrap', function()
+ command('set nowrap')
+ feed('i<TAB>test<ESC>')
+ meths.buf_set_extmark(
+ 0,
+ ns,
+ 0,
+ 0,
+ { virt_text = { { string.rep('a', 60), 'Special' } }, virt_text_pos = 'inline' }
+ )
+ feed('0')
+ screen:expect({
+ grid = [[
+ {10:aaaaaaaaaaaaaaaaaaaaaa} ^ test |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]],
+ })
+ end)
+
+ it('does not crash at column 0 when folded in a wide window', function()
+ screen:try_resize(82, 4)
+ command('hi! CursorLine guibg=NONE guifg=Red gui=NONE')
+ command('set cursorline')
+ insert([[
+ aaaaa
+ bbbbb
+ ccccc]])
+ meths.buf_set_extmark(0, ns, 0, 0, { virt_text = {{'foo'}}, virt_text_pos = 'inline' })
+ screen:expect{grid=[[
+ fooaaaaa |
+ bbbbb |
+ {16:cccc^c }|
+ |
+ ]]}
+ command('1,2fold')
+ screen:expect{grid=[[
+ {17:+-- 2 lines: aaaaa·······························································}|
+ {16:cccc^c }|
+ {1:~ }|
+ |
+ ]]}
+ feed('k')
+ screen:expect{grid=[[
+ {18:^+-- 2 lines: aaaaa·······························································}|
+ ccccc |
+ {1:~ }|
+ |
+ ]]}
+ end)
end)
describe('decorations: virtual lines', function()
@@ -1189,7 +2049,7 @@ describe('decorations: virtual lines', function()
ns = meths.create_namespace 'test'
end)
- local example_text = [[
+ local example_text2 = [[
if (h->n_buckets < new_n_buckets) { // expand
khkey_t *new_keys = (khkey_t *)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t));
h->keys = new_keys;
@@ -1200,7 +2060,7 @@ if (h->n_buckets < new_n_buckets) { // expand
}]]
it('works with one line', function()
- insert(example_text)
+ insert(example_text2)
feed 'gg'
meths.buf_set_extmark(0, ns, 1, 33, {
virt_lines={ {{">> ", "NonText"}, {"krealloc", "Identifier"}, {": change the size of an allocation"}}};
@@ -1309,7 +2169,7 @@ if (h->n_buckets < new_n_buckets) { // expand
end)
it('works with text at the beginning of the buffer', function()
- insert(example_text)
+ insert(example_text2)
feed 'gg'
screen:expect{grid=[[
@@ -1370,7 +2230,7 @@ if (h->n_buckets < new_n_buckets) { // expand
end)
it('works with text at the end of the buffer', function()
- insert(example_text)
+ insert(example_text2)
feed 'G'
screen:expect{grid=[[
@@ -1489,7 +2349,7 @@ if (h->n_buckets < new_n_buckets) { // expand
end)
it('works beyond end of the buffer with virt_lines_above', function()
- insert(example_text)
+ insert(example_text2)
feed 'G'
screen:expect{grid=[[
@@ -1760,7 +2620,7 @@ if (h->n_buckets < new_n_buckets) { // expand
end)
it('works with sign and numbercolumns', function()
- insert(example_text)
+ insert(example_text2)
feed 'gg'
command 'set number signcolumn=yes'
screen:expect{grid=[[
@@ -1826,7 +2686,7 @@ if (h->n_buckets < new_n_buckets) { // expand
it('works with hard tabs', function()
- insert(example_text)
+ insert(example_text2)
feed 'gg'
meths.buf_set_extmark(0, ns, 1, 0, {
virt_lines={ {{">>", "NonText"}, {"\tvery\ttabby", "Identifier"}, {"text\twith\ttabs"}}};
@@ -1910,10 +2770,10 @@ describe('decorations: signs', function()
}
ns = meths.create_namespace 'test'
- meths.win_set_option(0, 'signcolumn', 'auto:9')
+ meths.set_option_value('signcolumn', 'auto:9', {})
end)
- local example_text = [[
+ local example_test3 = [[
l1
l2
l3
@@ -1922,7 +2782,7 @@ l5
]]
it('can add a single sign (no end row)', function()
- insert(example_text)
+ insert(example_test3)
feed 'gg'
meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S'})
@@ -1943,7 +2803,7 @@ l5
end)
it('can add a single sign (with end row)', function()
- insert(example_text)
+ insert(example_test3)
feed 'gg'
meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S', end_row=1})
@@ -1965,7 +2825,7 @@ l5
it('can add multiple signs (single extmark)', function()
pending('TODO(lewis6991): Support ranged signs')
- insert(example_text)
+ insert(example_test3)
feed 'gg'
meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S', end_row = 2})
@@ -1987,7 +2847,7 @@ l5
it('can add multiple signs (multiple extmarks)', function()
pending('TODO(lewis6991): Support ranged signs')
- insert(example_text)
+ insert(example_test3)
feed'gg'
meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S1'})
@@ -2009,7 +2869,7 @@ l5
end)
it('can add multiple signs (multiple extmarks) 2', function()
- insert(example_text)
+ insert(example_test3)
feed 'gg'
meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S1'})
@@ -2049,7 +2909,7 @@ l5
it('can add multiple signs (multiple extmarks) 3', function()
pending('TODO(lewis6991): Support ranged signs')
- insert(example_text)
+ insert(example_test3)
feed 'gg'
meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S1', end_row=2})
@@ -2070,7 +2930,7 @@ l5
end)
it('can add multiple signs (multiple extmarks) 4', function()
- insert(example_text)
+ insert(example_test3)
feed 'gg'
meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S1', end_row=0})
@@ -2091,7 +2951,7 @@ l5
end)
it('works with old signs', function()
- insert(example_text)
+ insert(example_test3)
feed 'gg'
helpers.command('sign define Oldsign text=x')
@@ -2118,7 +2978,7 @@ l5
it('works with old signs (with range)', function()
pending('TODO(lewis6991): Support ranged signs')
- insert(example_text)
+ insert(example_test3)
feed 'gg'
helpers.command('sign define Oldsign text=x')
@@ -2147,7 +3007,7 @@ l5
it('can add a ranged sign (with start out of view)', function()
pending('TODO(lewis6991): Support ranged signs')
- insert(example_text)
+ insert(example_test3)
command 'set signcolumn=yes:2'
feed 'gg'
feed '2<C-e>'
@@ -2204,7 +3064,7 @@ l5
it('works with priority #19716', function()
screen:try_resize(20, 3)
- insert(example_text)
+ insert(example_test3)
feed 'gg'
helpers.command('sign define Oldsign text=O3')
@@ -2222,7 +3082,7 @@ l5
]]}
-- Check truncation works too
- meths.win_set_option(0, 'signcolumn', 'auto')
+ meths.set_option_value('signcolumn', 'auto', {})
screen:expect{grid=[[
S5^l1 |
@@ -2233,8 +3093,8 @@ l5
it('does not set signcolumn for signs without text', function()
screen:try_resize(20, 3)
- meths.win_set_option(0, 'signcolumn', 'auto')
- insert(example_text)
+ meths.set_option_value('signcolumn', 'auto', {})
+ insert(example_test3)
feed 'gg'
meths.buf_set_extmark(0, ns, 0, -1, {number_hl_group='Error'})
screen:expect{grid=[[
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index 28c16642f1..19ad340dd5 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -105,7 +105,7 @@ describe('float window', function()
it('opened with correct height', function()
local height = exec_lua([[
- vim.api.nvim_set_option("winheight", 20)
+ vim.go.winheight = 20
local bufnr = vim.api.nvim_create_buf(false, true)
local opts = {
@@ -127,7 +127,7 @@ describe('float window', function()
it('opened with correct width', function()
local width = exec_lua([[
- vim.api.nvim_set_option("winwidth", 20)
+ vim.go.winwidth = 20
local bufnr = vim.api.nvim_create_buf(false, true)
local opts = {
@@ -427,36 +427,36 @@ describe('float window', function()
it("no segfault when setting minimal style after clearing local 'fillchars' #19510", function()
local float_opts = {relative = 'editor', row = 1, col = 1, width = 1, height = 1}
local float_win = meths.open_win(0, true, float_opts)
- meths.win_set_option(float_win, 'fillchars', NIL)
+ meths.set_option_value('fillchars', NIL, {win=float_win.id})
float_opts.style = 'minimal'
meths.win_set_config(float_win, float_opts)
assert_alive()
- end)
+ end)
- it("should re-apply 'style' when present", function()
+ it("should re-apply 'style' when present", function()
local float_opts = {style = 'minimal', relative = 'editor', row = 1, col = 1, width = 1, height = 1}
local float_win = meths.open_win(0, true, float_opts)
- meths.win_set_option(float_win, 'number', true)
+ meths.set_option_value('number', true, { win = float_win })
float_opts.row = 2
meths.win_set_config(float_win, float_opts)
- eq(false, meths.win_get_option(float_win, 'number'))
+ eq(false, meths.get_option_value('number', { win = float_win }))
end)
it("should not re-apply 'style' when missing", function()
local float_opts = {style = 'minimal', relative = 'editor', row = 1, col = 1, width = 1, height = 1}
local float_win = meths.open_win(0, true, float_opts)
- meths.win_set_option(float_win, 'number', true)
+ meths.set_option_value('number', true, { win = float_win })
float_opts.row = 2
float_opts.style = nil
meths.win_set_config(float_win, float_opts)
- eq(true, meths.win_get_option(float_win, 'number'))
+ eq(true, meths.get_option_value('number', { win = float_win }))
end)
it("'scroll' is computed correctly when opening float with splitkeep=screen #20684", function()
- meths.set_option('splitkeep', 'screen')
+ meths.set_option_value('splitkeep', 'screen', {})
local float_opts = {relative = 'editor', row = 1, col = 1, width = 10, height = 10}
local float_win = meths.open_win(0, true, float_opts)
- eq(5, meths.win_get_option(float_win, 'scroll'))
+ eq(5, meths.get_option_value('scroll', {win=float_win.id}))
end)
describe('with only one tabpage,', function()
@@ -4553,8 +4553,8 @@ describe('float window', function()
describe('and completion', function()
before_each(function()
local buf = meths.create_buf(false,false)
- local win = meths.open_win(buf, true, {relative='editor', width=12, height=4, row=2, col=5})
- meths.win_set_option(win , 'winhl', 'Normal:ErrorMsg')
+ local win = meths.open_win(buf, true, {relative='editor', width=12, height=4, row=2, col=5}).id
+ meths.set_option_value('winhl', 'Normal:ErrorMsg', {win=win})
if multigrid then
screen:expect{grid=[[
## grid 1
@@ -7823,7 +7823,7 @@ describe('float window', function()
local buf = meths.create_buf(false,false)
meths.buf_set_lines(buf, 0, -1, true, {'foo', 'bar', 'baz'})
local float_win = meths.open_win(buf, false, {relative='editor', width=20, height=4, row=1, col=5})
- meths.win_set_option(float_win, 'winbar', 'floaty bar')
+ meths.set_option_value('winbar', 'floaty bar', {win=float_win.id})
if multigrid then
screen:expect{grid=[[
## grid 1
@@ -8079,10 +8079,13 @@ describe('float window', function()
[6] = {foreground = tonumber('0x332533'), background = tonumber('0xfff1ff')},
[7] = {background = tonumber('0xffcfff'), bold = true, foreground = tonumber('0x0000d8')},
[8] = {background = Screen.colors.LightMagenta, bold = true, foreground = Screen.colors.Blue1},
- [9] = {background = Screen.colors.LightMagenta, blend=30},
- [10] = {foreground = Screen.colors.Red, background = Screen.colors.LightMagenta, blend=0},
- [11] = {foreground = Screen.colors.Red, background = Screen.colors.LightMagenta, blend=80},
- [12] = {background = Screen.colors.LightMagenta, bold = true, foreground = Screen.colors.Blue1, blend=30},
+ [9] = {background = Screen.colors.LightMagenta, blend = 30},
+ [10] = {foreground = Screen.colors.Red, background = Screen.colors.LightMagenta, blend = 0},
+ [11] = {foreground = Screen.colors.Red, background = Screen.colors.LightMagenta, blend = 80},
+ [12] = {background = Screen.colors.LightMagenta, bold = true, foreground = Screen.colors.Blue1, blend = 30},
+ [13] = {background = Screen.colors.LightGray, blend = 30},
+ [14] = {foreground = Screen.colors.Grey0, background = Screen.colors.Grey88},
+ [15] = {foreground = tonumber('0x939393'), background = Screen.colors.Grey88},
})
insert([[
Lorem ipsum dolor sit amet, consectetur
@@ -8141,7 +8144,7 @@ describe('float window', function()
]])
end
- meths.win_set_option(win, "winblend", 30)
+ meths.set_option_value("winblend", 30, {win=win.id})
if multigrid then
screen:expect{grid=[[
## grid 1
@@ -8184,6 +8187,58 @@ describe('float window', function()
]])
end
+ -- Check that 'winblend' works with NormalNC highlight
+ meths.set_option_value('winhighlight', 'NormalNC:Visual', {win = win})
+ if multigrid then
+ screen:expect{grid=[[
+ ## grid 1
+ [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|
+ [3:--------------------------------------------------]|
+ ## grid 2
+ Ut enim ad minim veniam, quis nostrud |
+ exercitation ullamco laboris nisi ut aliquip ex |
+ ea commodo consequat. Duis aute irure dolor in |
+ reprehenderit in voluptate velit esse cillum |
+ dolore eu fugiat nulla pariatur. Excepteur sint |
+ occaecat cupidatat non proident, sunt in culpa |
+ qui officia deserunt mollit anim id est |
+ laborum^. |
+ ## grid 3
+ |
+ ## grid 5
+ {13:test }|
+ {13: }|
+ {13:popup text }|
+ ]], float_pos={
+ [5] = {{id = 1002}, "NW", 1, 2, 5, true, 50};
+ }}
+ else
+ screen:expect([[
+ Ut enim ad minim veniam, quis nostrud |
+ exercitation ullamco laboris nisi ut aliquip ex |
+ ea co{14:test}{15:o consequat}. Duis aute irure dolor in |
+ repre{15:henderit in vol}uptate velit esse cillum |
+ dolor{14:popup}{15:fugi}{14:text}{15:ul}la pariatur. Excepteur sint |
+ occaecat cupidatat non proident, sunt in culpa |
+ qui officia deserunt mollit anim id est |
+ laborum^. |
+ |
+ ]])
+ end
+
+ -- Also test with global NormalNC highlight
+ meths.set_option_value('winhighlight', '', {win = win})
+ command('hi link NormalNC Visual')
+ screen:expect_unchanged(true)
+ command('hi clear NormalNC')
+
command('hi SpecialRegion guifg=Red blend=0')
meths.buf_add_highlight(buf, -1, "SpecialRegion", 2, 0, -1)
if multigrid then
@@ -8397,7 +8452,7 @@ describe('float window', function()
-- at least. Also check invisible EndOfBuffer region blends correctly.
meths.buf_set_lines(buf, 0, -1, true, {" x x x xx", " x x x x"})
win = meths.open_win(buf, false, {relative='editor', width=12, height=3, row=0, col=11, style='minimal'})
- meths.win_set_option(win, 'winblend', 30)
+ meths.set_option_value('winblend', 30, {win=win.id})
screen:set_default_attr_ids({
[1] = {foreground = tonumber('0xb282b2'), background = tonumber('0xffcfff')},
[2] = {foreground = Screen.colors.Grey0, background = tonumber('0xffcfff')},
@@ -8639,7 +8694,7 @@ describe('float window', function()
it("correctly orders multiple opened floats (current last)", function()
local buf = meths.create_buf(false,false)
local win = meths.open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
- meths.win_set_option(win, "winhl", "Normal:ErrorMsg,EndOfBuffer:ErrorMsg")
+ meths.set_option_value("winhl", "Normal:ErrorMsg,EndOfBuffer:ErrorMsg", {win=win.id})
if multigrid then
screen:expect{grid=[[
@@ -8684,10 +8739,10 @@ describe('float window', function()
exec_lua [[
local buf = vim.api.nvim_create_buf(false,false)
local win = vim.api.nvim_open_win(buf, false, {relative='editor', width=16, height=2, row=3, col=8})
- vim.api.nvim_win_set_option(win, "winhl", "EndOfBuffer:Normal")
+ vim.wo[win].winhl = "EndOfBuffer:Normal"
buf = vim.api.nvim_create_buf(false,false)
win = vim.api.nvim_open_win(buf, true, {relative='editor', width=12, height=2, row=4, col=10})
- vim.api.nvim_win_set_option(win, "winhl", "Normal:Search,EndOfBuffer:Search")
+ vim.wo[win].winhl = "Normal:Search,EndOfBuffer:Search"
]]
if multigrid then
@@ -8744,7 +8799,7 @@ describe('float window', function()
it("correctly orders multiple opened floats (non-current last)", function()
local buf = meths.create_buf(false,false)
local win = meths.open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
- meths.win_set_option(win, "winhl", "Normal:ErrorMsg,EndOfBuffer:ErrorMsg")
+ meths.set_option_value("winhl", "Normal:ErrorMsg,EndOfBuffer:ErrorMsg", {win=win.id})
if multigrid then
screen:expect{grid=[[
@@ -8789,10 +8844,10 @@ describe('float window', function()
exec_lua [[
local buf = vim.api.nvim_create_buf(false,false)
local win = vim.api.nvim_open_win(buf, true, {relative='editor', width=12, height=2, row=4, col=10})
- vim.api.nvim_win_set_option(win, "winhl", "Normal:Search,EndOfBuffer:Search")
+ vim.wo[win].winhl = "Normal:Search,EndOfBuffer:Search"
buf = vim.api.nvim_create_buf(false,false)
win = vim.api.nvim_open_win(buf, false, {relative='editor', width=16, height=2, row=3, col=8})
- vim.api.nvim_win_set_option(win, "winhl", "EndOfBuffer:Normal")
+ vim.wo[win].winhl = "EndOfBuffer:Normal"
]]
if multigrid then
@@ -8849,11 +8904,11 @@ describe('float window', function()
it('can use z-index', function()
local buf = meths.create_buf(false,false)
local win1 = meths.open_win(buf, false, {relative='editor', width=20, height=3, row=1, col=5, zindex=30})
- meths.win_set_option(win1, "winhl", "Normal:ErrorMsg,EndOfBuffer:ErrorMsg")
+ meths.set_option_value("winhl", "Normal:ErrorMsg,EndOfBuffer:ErrorMsg", {win=win1.id})
local win2 = meths.open_win(buf, false, {relative='editor', width=20, height=3, row=2, col=6, zindex=50})
- meths.win_set_option(win2, "winhl", "Normal:Search,EndOfBuffer:Search")
+ meths.set_option_value("winhl", "Normal:Search,EndOfBuffer:Search", {win=win2.id})
local win3 = meths.open_win(buf, false, {relative='editor', width=20, height=3, row=3, col=7, zindex=40})
- meths.win_set_option(win3, "winhl", "Normal:Question,EndOfBuffer:Question")
+ meths.set_option_value("winhl", "Normal:Question,EndOfBuffer:Question", {win=win3.id})
if multigrid then
screen:expect{grid=[[
@@ -8912,7 +8967,7 @@ describe('float window', function()
it('can use winbar', function()
local buf = meths.create_buf(false,false)
local win1 = meths.open_win(buf, false, {relative='editor', width=15, height=3, row=1, col=5})
- meths.win_set_option(win1, 'winbar', 'floaty bar')
+ meths.set_option_value('winbar', 'floaty bar', {win=win1.id})
if multigrid then
screen:expect{grid=[[
diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua
index a99b77f707..520979a2c2 100644
--- a/test/functional/ui/fold_spec.lua
+++ b/test/functional/ui/fold_spec.lua
@@ -42,7 +42,10 @@ describe("folded lines", function()
[9] = {bold = true, foreground = Screen.colors.Brown},
[10] = {background = Screen.colors.LightGrey, underline = true},
[11] = {bold=true},
- [12] = {background = Screen.colors.Grey90},
+ [12] = {foreground = Screen.colors.Red},
+ [13] = {foreground = Screen.colors.Red, background = Screen.colors.LightGrey},
+ [14] = {background = Screen.colors.Red},
+ [15] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.Red},
})
end)
@@ -86,7 +89,7 @@ describe("folded lines", function()
end
end)
- it("highlights with CursorLineFold when 'cursorline' is set", function()
+ local function test_folded_cursorline()
command("set number cursorline foldcolumn=2")
command("hi link CursorLineFold Search")
insert(content1)
@@ -138,7 +141,7 @@ describe("folded lines", function()
[2:---------------------------------------------]|
[3:---------------------------------------------]|
## grid 2
- {6:+ }{9: 1 }{12:^+-- 4 lines: This is a················}|
+ {6:+ }{9: 1 }{13:^+-- 4 lines: This is a················}|
{7: }{8: 5 }in his cave. |
{7: }{8: 6 } |
{1:~ }|
@@ -150,7 +153,7 @@ describe("folded lines", function()
]])
else
screen:expect([[
- {6:+ }{9: 1 }{12:^+-- 4 lines: This is a················}|
+ {6:+ }{9: 1 }{13:^+-- 4 lines: This is a················}|
{7: }{8: 5 }in his cave. |
{7: }{8: 6 } |
{1:~ }|
@@ -179,7 +182,7 @@ describe("folded lines", function()
[2:---------------------------------------------]|
[3:---------------------------------------------]|
## grid 2
- {7:+ }{8: 1 }{12:^+-- 4 lines: This is a················}|
+ {7:+ }{8: 1 }{13:^+-- 4 lines: This is a················}|
{7: }{8: 5 }in his cave. |
{7: }{8: 6 } |
{1:~ }|
@@ -191,7 +194,7 @@ describe("folded lines", function()
]])
else
screen:expect([[
- {7:+ }{8: 1 }{12:^+-- 4 lines: This is a················}|
+ {7:+ }{8: 1 }{13:^+-- 4 lines: This is a················}|
{7: }{8: 5 }in his cave. |
{7: }{8: 6 } |
{1:~ }|
@@ -236,6 +239,22 @@ describe("folded lines", function()
|
]])
end
+ end
+
+ describe("when 'cursorline' is set", function()
+ it('with high-priority CursorLine', function()
+ command("hi! CursorLine guibg=NONE guifg=Red gui=NONE")
+ test_folded_cursorline()
+ end)
+
+ it('with low-priority CursorLine', function()
+ command("hi! CursorLine guibg=NONE guifg=NONE gui=underline")
+ local attrs = screen:get_default_attr_ids()
+ attrs[12] = {underline = true}
+ attrs[13] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey, underline = true}
+ screen:set_default_attr_ids(attrs)
+ test_folded_cursorline()
+ end)
end)
it("work with spell", function()
@@ -967,8 +986,8 @@ describe("folded lines", function()
it("works with multibyte text", function()
-- Currently the only allowed value of 'maxcombine'
- eq(6, meths.get_option('maxcombine'))
- eq(true, meths.get_option('arabicshape'))
+ eq(6, meths.get_option_value('maxcombine', {}))
+ eq(true, meths.get_option_value('arabicshape', {}))
insert([[
å 语 x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢͟ العَرَبِيَّة
möre text]])
@@ -2013,6 +2032,57 @@ describe("folded lines", function()
]])
end
end)
+
+ it('Folded and Visual highlights are combined #19691', function()
+ command('hi! Visual guibg=Red')
+ insert([[
+ " foo
+ " {{{1
+ set nocp
+ " }}}1
+ " bar
+ " {{{1
+ set foldmethod=marker
+ " }}}1
+ " baz]])
+ feed('gg')
+ command('source')
+ feed('<C-V>G3l')
+ if multigrid then
+ screen:expect([[
+ ## grid 1
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [2:---------------------------------------------]|
+ [3:---------------------------------------------]|
+ ## grid 2
+ {14:" fo}o |
+ {15:+-- }{5: 3 lines: "······························}|
+ {14:" ba}r |
+ {15:+-- }{5: 3 lines: "······························}|
+ {14:" b}^az |
+ {1:~ }|
+ {1:~ }|
+ ## grid 3
+ {11:-- VISUAL BLOCK --} |
+ ]])
+ else
+ screen:expect([[
+ {14:" fo}o |
+ {15:+-- }{5: 3 lines: "······························}|
+ {14:" ba}r |
+ {15:+-- }{5: 3 lines: "······························}|
+ {14:" b}^az |
+ {1:~ }|
+ {1:~ }|
+ {11:-- VISUAL BLOCK --} |
+ ]])
+ end
+ end)
end
describe("with ext_multigrid", function()
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua
index 28f489783b..23b200bd24 100644
--- a/test/functional/ui/inccommand_spec.lua
+++ b/test/functional/ui/inccommand_spec.lua
@@ -2,7 +2,6 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local command = helpers.command
-local curbufmeths = helpers.curbufmeths
local eq = helpers.eq
local eval = helpers.eval
local feed_command = helpers.feed_command
@@ -178,8 +177,8 @@ describe(":substitute, 'inccommand' preserves", function()
feed_command("set inccommand=" .. case)
insert("as")
feed(":%s/as/glork/<enter>")
- eq(meths.get_option('undolevels'), 139)
- eq(curbufmeths.get_option('undolevels'), 34)
+ eq(meths.get_option_value('undolevels', {scope='global'}), 139)
+ eq(meths.get_option_value('undolevels', {buf=0}), 34)
end)
end
@@ -1192,7 +1191,7 @@ describe(":substitute, inccommand=split", function()
it("deactivates if 'redrawtime' is exceeded #5602", function()
-- prevent redraws from 'incsearch'
- meths.set_option('incsearch', false)
+ meths.set_option_value('incsearch', false, {})
-- Assert that 'inccommand' is ENABLED initially.
eq("split", eval("&inccommand"))
-- Set 'redrawtime' to minimal value, to ensure timeout is triggered.
@@ -2465,16 +2464,14 @@ describe(":substitute", function()
end)
it("inccommand=split, contraction of two subsequent NL chars", function()
- -- luacheck: push ignore 611
local text = [[
AAA AA
-
+
BBB BB
-
+
CCC CC
-
+
]]
- -- luacheck: pop
-- This used to crash, but more than 20 highlight entries are required
-- to reproduce it (so that the marktree has multiple nodes)
@@ -2501,16 +2498,14 @@ describe(":substitute", function()
end)
it("inccommand=nosplit, contraction of two subsequent NL chars", function()
- -- luacheck: push ignore 611
local text = [[
AAA AA
-
+
BBB BB
-
+
CCC CC
-
+
]]
- -- luacheck: pop
common_setup(screen, "nosplit", string.rep(text,10))
feed(":%s/\\n\\n/<c-v><c-m>/g")
diff --git a/test/functional/ui/inccommand_user_spec.lua b/test/functional/ui/inccommand_user_spec.lua
index 43e9b94feb..6329ece40a 100644
--- a/test/functional/ui/inccommand_user_spec.lua
+++ b/test/functional/ui/inccommand_user_spec.lua
@@ -391,7 +391,7 @@ describe("'inccommand' for user commands", function()
vim.api.nvim_create_user_command('Replace', function() end, {
nargs = '*',
preview = function()
- vim.api.nvim_set_option('inccommand', 'split')
+ vim.api.nvim_set_option_value('inccommand', 'split', {})
return 2
end,
})
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index 1a7fe26d26..46a42e5beb 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -1273,7 +1273,7 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
{1:~ }|
|
]])
- eq(1, meths.get_option('cmdheight'))
+ eq(1, meths.get_option_value('cmdheight', {}))
end)
end)
diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
index e55804e29f..d8739e1c31 100644
--- a/test/functional/ui/mouse_spec.lua
+++ b/test/functional/ui/mouse_spec.lua
@@ -11,8 +11,8 @@ describe('ui/mouse/input', function()
before_each(function()
clear()
- meths.set_option('mouse', 'a')
- meths.set_option('list', true)
+ meths.set_option_value('mouse', 'a', {})
+ meths.set_option_value('list', true, {})
-- NB: this is weird, but mostly irrelevant to the test
-- So I didn't bother to change it
command('set listchars=eol:$')
@@ -64,7 +64,7 @@ describe('ui/mouse/input', function()
end)
it("in external ui works with unset 'mouse'", function()
- meths.set_option('mouse', '')
+ meths.set_option_value('mouse', '', {})
feed('<LeftMouse><2,1>')
screen:expect{grid=[[
testing |
@@ -379,7 +379,7 @@ describe('ui/mouse/input', function()
end)
it('left click in default tabline (position 24) closes tab', function()
- meths.set_option('hidden', true)
+ meths.set_option_value('hidden', true, {})
feed_command('%delete')
insert('this is foo')
feed_command('silent file foo | tabnew | file bar')
@@ -402,7 +402,7 @@ describe('ui/mouse/input', function()
end)
it('double click in default tabline (position 4) opens new tab', function()
- meths.set_option('hidden', true)
+ meths.set_option_value('hidden', true, {})
feed_command('%delete')
insert('this is foo')
feed_command('silent file foo | tabnew | file bar')
@@ -437,8 +437,8 @@ describe('ui/mouse/input', function()
return call('Test', a:000 + [2])
endfunction
]])
- meths.set_option('tabline', '%@Test@test%X-%5@Test2@test2')
- meths.set_option('showtabline', 2)
+ meths.set_option_value('tabline', '%@Test@test%X-%5@Test2@test2', {})
+ meths.set_option_value('showtabline', 2, {})
screen:expect([[
{fill:test-test2 }|
testing |
@@ -786,7 +786,7 @@ describe('ui/mouse/input', function()
end)
it('ctrl + left click will search for a tag', function()
- meths.set_option('tags', './non-existent-tags-file')
+ meths.set_option_value('tags', './non-existent-tags-file', {})
feed('<C-LeftMouse><0,0>')
screen:expect([[
{6:E433: No tags file} |
@@ -1577,9 +1577,9 @@ describe('ui/mouse/input', function()
end)
it('getmousepos works correctly', function()
- local winwidth = meths.get_option('winwidth')
+ local winwidth = meths.get_option_value('winwidth', {})
-- Set winwidth=1 so that window sizes don't change.
- meths.set_option('winwidth', 1)
+ meths.set_option_value('winwidth', 1, {})
command('tabedit')
local tabpage = meths.get_current_tabpage()
insert('hello')
@@ -1597,8 +1597,8 @@ describe('ui/mouse/input', function()
}
local float = meths.open_win(meths.get_current_buf(), false, opts)
command('redraw')
- local lines = meths.get_option('lines')
- local columns = meths.get_option('columns')
+ local lines = meths.get_option_value('lines', {})
+ local columns = meths.get_option_value('columns', {})
-- Test that screenrow and screencol are set properly for all positions.
for row = 0, lines - 1 do
@@ -1696,7 +1696,7 @@ describe('ui/mouse/input', function()
-- Restore state and release mouse.
command('tabclose!')
- meths.set_option('winwidth', winwidth)
+ meths.set_option_value('winwidth', winwidth, {})
meths.input_mouse('left', 'release', '', 0, 0, 0)
end)
diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua
index 4c04bcb54e..8918c46de6 100644
--- a/test/functional/ui/multigrid_spec.lua
+++ b/test/functional/ui/multigrid_spec.lua
@@ -3555,7 +3555,7 @@ describe('ext_multigrid', function()
end)
it('with winbar dragging statusline with mouse works correctly', function()
- meths.set_option('winbar', 'Set Up The Bars')
+ meths.set_option_value('winbar', 'Set Up The Bars', {})
command('split')
screen:expect([[
## grid 1
@@ -3695,7 +3695,7 @@ describe('ext_multigrid', function()
{1:~ }|
{1:~ }|
]])
- eq(3, meths.get_option('cmdheight'))
+ eq(3, meths.get_option_value('cmdheight', {}))
meths.input_mouse('left', 'drag', '', 1, 12, 10)
screen:expect([[
@@ -3730,6 +3730,6 @@ describe('ext_multigrid', function()
{1:~ }|
{1:~ }|
]])
- eq(1, meths.get_option('cmdheight'))
+ eq(1, meths.get_option_value('cmdheight', {}))
end)
end)
diff --git a/test/functional/ui/quickfix_spec.lua b/test/functional/ui/quickfix_spec.lua
index b0d89ee3b6..df43871e60 100644
--- a/test/functional/ui/quickfix_spec.lua
+++ b/test/functional/ui/quickfix_spec.lua
@@ -27,7 +27,7 @@ describe('quickfix selection highlight', function()
[12] = {foreground = Screen.colors.Brown, background = Screen.colors.Fuchsia},
})
- meths.set_option('errorformat', '%m %l')
+ meths.set_option_value('errorformat', '%m %l', {})
command('syntax on')
command('highlight Search guibg=Green')
diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua
index 6b05bd01c2..b31e40d4ab 100644
--- a/test/functional/ui/screen_basic_spec.lua
+++ b/test/functional/ui/screen_basic_spec.lua
@@ -2,12 +2,10 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local spawn, set_session, clear = helpers.spawn, helpers.set_session, helpers.clear
local feed, command = helpers.feed, helpers.command
-local curwin = helpers.curwin
local insert = helpers.insert
local eq = helpers.eq
local eval = helpers.eval
-local funcs, meths, exec_lua = helpers.funcs, helpers.meths, helpers.exec_lua
-local is_os = helpers.is_os
+local funcs, meths = helpers.funcs, helpers.meths
describe('screen', function()
local screen
@@ -120,123 +118,6 @@ local function screen_tests(linegrid)
eq(expected, screen.title)
end)
end)
-
- it('has correct default title with unnamed file', function()
- local expected = '[No Name] - NVIM'
- command('set title')
- screen:expect(function()
- eq(expected, screen.title)
- end)
- end)
-
- it('has correct default title with named file', function()
- local expected = (is_os('win') and 'myfile (C:\\mydir) - NVIM' or 'myfile (/mydir) - NVIM')
- command('set title')
- command(is_os('win') and 'file C:\\mydir\\myfile' or 'file /mydir/myfile')
- screen:expect(function()
- eq(expected, screen.title)
- end)
- end)
-
- describe('is not changed by', function()
- local file1 = is_os('win') and 'C:\\mydir\\myfile1' or '/mydir/myfile1'
- local file2 = is_os('win') and 'C:\\mydir\\myfile2' or '/mydir/myfile2'
- local expected = (is_os('win') and 'myfile1 (C:\\mydir) - NVIM' or 'myfile1 (/mydir) - NVIM')
- local buf2
-
- before_each(function()
- command('edit '..file1)
- buf2 = funcs.bufadd(file2)
- command('set title')
- end)
-
- it('calling setbufvar() to set an option in a hidden buffer from i_CTRL-R', function()
- command([[inoremap <F2> <C-R>=setbufvar(]]..buf2..[[, '&autoindent', 1) ? '' : ''<CR>]])
- feed('i<F2><Esc>')
- command('redraw!')
- screen:expect(function()
- eq(expected, screen.title)
- end)
- end)
-
- it('an RPC call to nvim_buf_set_option in a hidden buffer', function()
- meths.buf_set_option(buf2, 'autoindent', true)
- command('redraw!')
- screen:expect(function()
- eq(expected, screen.title)
- end)
- end)
-
- it('a Lua callback calling nvim_buf_set_option in a hidden buffer', function()
- exec_lua(string.format([[
- vim.schedule(function()
- vim.api.nvim_buf_set_option(%d, 'autoindent', true)
- end)
- ]], buf2))
- command('redraw!')
- screen:expect(function()
- eq(expected, screen.title)
- end)
- end)
-
- it('a Lua callback calling nvim_buf_call in a hidden buffer', function()
- exec_lua(string.format([[
- vim.schedule(function()
- vim.api.nvim_buf_call(%d, function() end)
- end)
- ]], buf2))
- command('redraw!')
- screen:expect(function()
- eq(expected, screen.title)
- end)
- end)
-
- it('setting the buffer of another window using RPC', function()
- local oldwin = curwin().id
- command('split')
- meths.win_set_buf(oldwin, buf2)
- command('redraw!')
- screen:expect(function()
- eq(expected, screen.title)
- end)
- end)
-
- it('setting the buffer of another window using Lua callback', function()
- local oldwin = curwin().id
- command('split')
- exec_lua(string.format([[
- vim.schedule(function()
- vim.api.nvim_win_set_buf(%d, %d)
- end)
- ]], oldwin, buf2))
- command('redraw!')
- screen:expect(function()
- eq(expected, screen.title)
- end)
- end)
-
- it('creating a floating window using RPC', function()
- meths.open_win(buf2, false, {
- relative = 'editor', width = 5, height = 5, row = 0, col = 0,
- })
- command('redraw!')
- screen:expect(function()
- eq(expected, screen.title)
- end)
- end)
-
- it('creating a floating window using Lua callback', function()
- exec_lua(string.format([[
- vim.api.nvim_open_win(%d, false, {
- relative = 'editor', width = 5, height = 5, row = 0, col = 0,
- })
- ]], buf2))
- command('redraw!')
- screen:expect(function()
- eq(expected, screen.title)
- end)
- end)
- end)
end)
describe(':set icon', function()
@@ -947,7 +828,7 @@ local function screen_tests(linegrid)
command([[autocmd VimResized * redrawtabline]])
command([[autocmd VimResized * lua vim.api.nvim_echo({ { 'Hello' } }, false, {})]])
command([[autocmd VimResized * let g:echospace = v:echospace]])
- meths.set_option('showtabline', 2)
+ meths.set_option_value('showtabline', 2, {})
screen:expect([[
{2: + [No Name] }{3: }|
resiz^e |
@@ -1175,8 +1056,8 @@ it('CTRL-F or CTRL-B scrolls a page after UI attach/resize #20605', function()
clear()
local screen = Screen.new(100, 100)
screen:attach()
- eq(100, meths.get_option('lines'))
- eq(99, meths.get_option('window'))
+ eq(100, meths.get_option_value('lines', {}))
+ eq(99, meths.get_option_value('window', {}))
eq(99, meths.win_get_height(0))
feed('1000o<Esc>')
eq(903, funcs.line('w0'))
@@ -1190,8 +1071,8 @@ it('CTRL-F or CTRL-B scrolls a page after UI attach/resize #20605', function()
eq(903, funcs.line('w0'))
feed('G')
screen:try_resize(50, 50)
- eq(50, meths.get_option('lines'))
- eq(49, meths.get_option('window'))
+ eq(50, meths.get_option_value('lines', {}))
+ eq(49, meths.get_option_value('window', {}))
eq(49, meths.win_get_height(0))
eq(953, funcs.line('w0'))
feed('<C-B>')
diff --git a/test/functional/ui/spell_spec.lua b/test/functional/ui/spell_spec.lua
index 15819aef40..630d0d0948 100644
--- a/test/functional/ui/spell_spec.lua
+++ b/test/functional/ui/spell_spec.lua
@@ -3,9 +3,9 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
+local exec = helpers.exec
local feed = helpers.feed
local insert = helpers.insert
-local command = helpers.command
local meths = helpers.meths
local curbufmeths = helpers.curbufmeths
local is_os = helpers.is_os
@@ -27,12 +27,14 @@ describe("'spell'", function()
[6] = {foreground = Screen.colors.Red},
[7] = {foreground = Screen.colors.Blue},
[8] = {foreground = Screen.colors.Blue, special = Screen.colors.Red, undercurl = true},
+ [9] = {bold = true},
+ [10] = {background = Screen.colors.LightGrey, foreground = Screen.colors.DarkBlue},
})
end)
it('joins long lines #7937', function()
if is_os('openbsd') then pending('FIXME #12104', function() end) return end
- command('set spell')
+ exec('set spell')
insert([[
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
@@ -57,31 +59,165 @@ describe("'spell'", function()
-- oldtest: Test_spell_screendump()
it('has correct highlight at start of line', function()
- insert([[
- "This is some text without any spell errors. Everything",
- "should just be black, nothing wrong here.",
- "",
- "This line has a sepll error. and missing caps.",
- "And and this is the the duplication.",
- "with missing caps here.",
+ exec([=[
+ call setline(1, [
+ \"This is some text without any spell errors. Everything",
+ \"should just be black, nothing wrong here.",
+ \"",
+ \"This line has a sepll error. and missing caps.",
+ \"And and this is the the duplication.",
+ \"with missing caps here.",
+ \])
+ set spell spelllang=en_nz
+ ]=])
+ screen:expect([[
+ ^This is some text without any spell errors. Everything |
+ should just be black, nothing wrong here. |
+ |
+ This line has a {1:sepll} error. {2:and} missing caps. |
+ {1:And and} this is {1:the the} duplication. |
+ {2:with} missing caps here. |
+ {0:~ }|
+ |
]])
- command('set spell spelllang=en_nz')
+ end)
+
+ -- oldtest: Test_spell_screendump_spellcap()
+ it('SpellCap highlight at start of line', function()
+ exec([=[
+ call setline(1, [
+ \" This line has a sepll error. and missing caps and trailing spaces. ",
+ \"another missing cap here.",
+ \"",
+ \"and here.",
+ \" ",
+ \"and here."
+ \])
+ set spell spelllang=en
+ ]=])
screen:expect([[
- "This is some text without any spell errors. Everything", |
- "should just be black, nothing wrong here.", |
- "", |
- "This line has a {1:sepll} error. {2:and} missing caps.", |
- "{1:And and} this is {1:the the} duplication.", |
- "with missing caps here.", |
- ^ |
- |
+ ^ This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. |
+ {2:another} missing cap here. |
+ |
+ {2:and} here. |
+ |
+ {2:and} here. |
+ {0:~ }|
+ |
+ ]])
+ -- After adding word missing Cap in next line is updated
+ feed('3GANot<Esc>')
+ screen:expect([[
+ This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. |
+ {2:another} missing cap here. |
+ No^t |
+ and here. |
+ |
+ {2:and} here. |
+ {0:~ }|
+ |
+ ]])
+ -- Deleting a full stop removes missing Cap in next line
+ feed('5Gdd<C-L>k$x')
+ screen:expect([[
+ This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. |
+ {2:another} missing cap here. |
+ Not |
+ and her^e |
+ and here. |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ -- Undo also updates the next line (go to command line to remove message)
+ feed('u:<Esc>')
+ screen:expect([[
+ This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. |
+ {2:another} missing cap here. |
+ Not |
+ and here^. |
+ {2:and} here. |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ -- Folding an empty line does not remove Cap in next line
+ feed('uzfk:<Esc>')
+ screen:expect([[
+ This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. |
+ {2:another} missing cap here. |
+ Not |
+ {10:^+-- 2 lines: and here.·························································}|
+ {2:and} here. |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ -- Folding the end of a sentence does not remove Cap in next line
+ -- and editing a line does not remove Cap in current line
+ feed('Jzfkk$x')
+ screen:expect([[
+ This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. |
+ {2:another} missing cap her^e |
+ {10:+-- 2 lines: Not·······························································}|
+ {2:and} here. |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ -- Cap is correctly applied in the first row of a window
+ feed('<C-E><C-L>')
+ screen:expect([[
+ {2:another} missing cap her^e |
+ {10:+-- 2 lines: Not·······························································}|
+ {2:and} here. |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ end)
+
+ -- oldtest: Test_spell_compatible()
+ it([[redraws properly when using "C" and "$" is in 'cpo']], function()
+ exec([=[
+ call setline(1, [
+ \ "test "->repeat(20),
+ \ "",
+ \ "end",
+ \ ])
+ set spell cpo+=$
+ ]=])
+ feed('51|C')
+ screen:expect([[
+ {2:test} test test test test test test test test test ^test test test test test test |
+ test test test test$ |
+ |
+ {2:end} |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {9:-- INSERT --} |
+ ]])
+ feed('x')
+ screen:expect([[
+ {2:test} test test test test test test test test test x^est test test test test test |
+ test test test test$ |
+ |
+ {2:end} |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {9:-- INSERT --} |
]])
end)
it('extmarks, "noplainbuffer" and syntax #20385 #23398', function()
- command('set filetype=c')
- command('syntax on')
- command('set spell')
+ exec('set filetype=c')
+ exec('syntax on')
+ exec('set spell')
insert([[
#include <stdbool.h>
bool func(void);
@@ -119,7 +255,7 @@ describe("'spell'", function()
{0:~ }|
{6:search hit BOTTOM, continuing at TOP} |
]])
- command('echo ""')
+ exec('echo ""')
local ns = meths.create_namespace("spell")
-- extmark with spell=true enables spell
local id = curbufmeths.set_extmark(ns, 1, 4, { end_row = 1, end_col = 10, spell = true })
@@ -168,7 +304,7 @@ describe("'spell'", function()
{0:~ }|
{6:search hit TOP, continuing at BOTTOM} |
]])
- command('echo ""')
+ exec('echo ""')
curbufmeths.del_extmark(ns, id)
screen:expect([[
{3:#include }{4:<stdbool.h>} |
@@ -192,7 +328,7 @@ describe("'spell'", function()
|
]])
-- "noplainbuffer" shouldn't change spellchecking behavior with syntax enabled
- command('set spelloptions+=noplainbuffer')
+ exec('set spelloptions+=noplainbuffer')
screen:expect_unchanged()
feed('[s')
screen:expect([[
@@ -206,7 +342,7 @@ describe("'spell'", function()
|
]])
-- no spellchecking with "noplainbuffer" and syntax disabled
- command('syntax off')
+ exec('syntax off')
screen:expect([[
#include <stdbool.h> |
bool func(void); |
@@ -228,9 +364,9 @@ describe("'spell'", function()
{0:~ }|
{6:search hit BOTTOM, continuing at TOP} |
]])
- command('echo ""')
+ exec('echo ""')
-- everything is spellchecked without "noplainbuffer" with syntax disabled
- command('set spelloptions&')
+ exec('set spelloptions&')
screen:expect([[
#include <{1:stdbool}.h> |
{1:bool} {1:func}(void); |
@@ -254,4 +390,19 @@ describe("'spell'", function()
]])
end)
+ it('and syntax does not clear extmark highlighting at the start of a word', function()
+ screen:try_resize(43, 3)
+ exec([[
+ set spell
+ syntax match Constant "^.*$"
+ call setline(1, "This is some text without any spell errors.")
+ ]])
+ local ns = meths.create_namespace("spell")
+ curbufmeths.set_extmark(ns, 0, 0, { hl_group = 'WarningMsg', end_col = 43 })
+ screen:expect([[
+ {6:^This is some text without any spell errors.}|
+ {0:~ }|
+ |
+ ]])
+ end)
end)
diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua
index 3b41d3684a..c218bd8fd6 100644
--- a/test/functional/ui/statuscolumn_spec.lua
+++ b/test/functional/ui/statuscolumn_spec.lua
@@ -196,8 +196,10 @@ describe('statuscolumn', function()
[2] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGrey},
[3] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey},
[4] = {bold = true, foreground = Screen.colors.Brown},
- [5] = {background = Screen.colors.Grey90},
+ [5] = {foreground = Screen.colors.Red},
+ [6] = {foreground = Screen.colors.Red, background = Screen.colors.LightGrey},
})
+ command('hi! CursorLine guifg=Red guibg=NONE')
screen:expect([[
{1: 4│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{1: │ }a |
@@ -214,7 +216,7 @@ describe('statuscolumn', function()
{1:10│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{0:@@@}|
|
]])
- command("set stc=%C%s%=%l│\\ ")
+ command([[set stc=%C%s%=%l│\ ]])
screen:expect_unchanged()
command('set signcolumn=auto:2 foldcolumn=auto')
command('sign define piet1 text=>> texthl=LineNr')
@@ -268,7 +270,7 @@ describe('statuscolumn', function()
{2: }{1: │}{2: }{1: }aaaaaa |
{2: }{1: 7│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaa |
- {2:+}{4: 8│}{2: }{4: }{5:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
+ {2:+}{4: 8│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
{2: }{1: 9│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaa |
{2: }{1:10│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
@@ -286,7 +288,7 @@ describe('statuscolumn', function()
{2: }{1: 6│}{2: }{1: }aaaaaa |
{2: }{1: 7│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: 7│}{2: }{1: }aaaaaa |
- {2:+}{4: 8│}{2: }{4: }{5:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
+ {2:+}{4: 8│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
{2: }{1: 9│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: 9│}{2: }{1: }aaaaaa |
{2: }{1:10│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
@@ -304,7 +306,7 @@ describe('statuscolumn', function()
{2: }{1: 2│}{2: }{1: }aaaaaa |
{2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: 1│}{2: }{1: }aaaaaa |
- {2:+}{4: 0│}{2: }{4: }{5:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
+ {2:+}{4: 0│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
{2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: 1│}{2: }{1: }aaaaaa |
{2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
@@ -321,7 +323,7 @@ describe('statuscolumn', function()
{2: }{1: │}{2: }{1: }aaaaaa |
{2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaa |
- {2:+}{4: 0│}{2: }{4: }{5:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
+ {2:+}{4: 0│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
{2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaa |
{2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
@@ -346,7 +348,7 @@ describe('statuscolumn', function()
{2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaa |
{2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaa |
- {2:+}{4: 0│}{2: }{4: }{5:^+-- 1 line: aaaaaaaaaaaaaaaaa}|
+ {2:+}{4: 0│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaa}|
{2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaa |
{2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
@@ -372,7 +374,7 @@ describe('statuscolumn', function()
{1:wrapped 1 6}aaaaaaaa |
{1:buffer 0 7}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{1:wrapped 1 7}aaaaaaaa |
- {4:buffer 0 8}{5:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
+ {4:buffer 0 8}{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
{1:buffer 0 9}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{1:wrapped 1 9}aaaaaaaa |
|
@@ -674,4 +676,16 @@ describe('statuscolumn', function()
]])
eq(2, eval('g:stcnr'))
end)
+
+ it('does not wrap multibyte characters at the end of a line', function()
+ screen:try_resize(33, 4)
+ command([[set spell stc=%l\ ]])
+ command('call setline(8, "This is a line that contains ᶏ multibyte character.")')
+ screen:expect([[
+ 8 ^This is a line that contains ᶏ|
+ multibyte character. |
+ 9 aaaaa |
+ |
+ ]])
+ end)
end)
diff --git a/test/functional/ui/statusline_spec.lua b/test/functional/ui/statusline_spec.lua
index 5ea4eade4e..5afa912be6 100644
--- a/test/functional/ui/statusline_spec.lua
+++ b/test/functional/ui/statusline_spec.lua
@@ -34,7 +34,7 @@ for _, model in ipairs(mousemodels) do
end)
it('works', function()
- meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
+ meths.set_option_value('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T', {})
meths.input_mouse('left', 'press', '', 0, 6, 17)
eq('0 1 l', eval("g:testvar"))
meths.input_mouse('left', 'press', '', 0, 6, 17)
@@ -54,7 +54,7 @@ for _, model in ipairs(mousemodels) do
end)
it('works for winbar', function()
- meths.set_option('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
+ meths.set_option_value('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T', {})
meths.input_mouse('left', 'press', '', 0, 0, 17)
eq('0 1 l', eval("g:testvar"))
meths.input_mouse('right', 'press', '', 0, 0, 17)
@@ -72,8 +72,8 @@ for _, model in ipairs(mousemodels) do
it('works when there are multiple windows', function()
command('split')
- meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
- meths.set_option('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
+ meths.set_option_value('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T', {})
+ meths.set_option_value('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T', {})
meths.input_mouse('left', 'press', '', 0, 0, 17)
eq('0 1 l', eval("g:testvar"))
meths.input_mouse('right', 'press', '', 0, 4, 17)
@@ -90,23 +90,23 @@ for _, model in ipairs(mousemodels) do
vim.g.testvar = string.format("%d %d %s", minwid, clicks, button)
end
]])
- meths.set_option('statusline', 'Not clicky stuff %0@v:lua.clicky_func@Clicky stuff%T')
+ meths.set_option_value('statusline', 'Not clicky stuff %0@v:lua.clicky_func@Clicky stuff%T', {})
meths.input_mouse('left', 'press', '', 0, 6, 17)
eq('0 1 l', eval("g:testvar"))
end)
it('ignores unsupported click items', function()
command('tabnew | tabprevious')
- meths.set_option('statusline', '%2TNot clicky stuff%T')
+ meths.set_option_value('statusline', '%2TNot clicky stuff%T', {})
meths.input_mouse('left', 'press', '', 0, 6, 0)
eq(1, meths.get_current_tabpage().id)
- meths.set_option('statusline', '%2XNot clicky stuff%X')
+ meths.set_option_value('statusline', '%2XNot clicky stuff%X', {})
meths.input_mouse('left', 'press', '', 0, 6, 0)
eq(2, #meths.list_tabpages())
end)
it("right click works when statusline isn't focused #18994", function()
- meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
+ meths.set_option_value('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T', {})
meths.input_mouse('right', 'press', '', 0, 6, 17)
eq('0 1 r', eval("g:testvar"))
meths.input_mouse('right', 'press', '', 0, 6, 17)
@@ -114,7 +114,7 @@ for _, model in ipairs(mousemodels) do
end)
it("works with modifiers #18994", function()
- meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
+ meths.set_option_value('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T', {})
-- Note: alternate between left and right mouse buttons to avoid triggering multiclicks
meths.input_mouse('left', 'press', 'S', 0, 6, 17)
eq('0 1 l(s )', eval("g:testvar"))
@@ -143,7 +143,7 @@ for _, model in ipairs(mousemodels) do
it("works for global statusline with vertical splits #19186", function()
command('set laststatus=3')
- meths.set_option('statusline', '%0@MyClickFunc@Clicky stuff%T %= %0@MyClickFunc@Clicky stuff%T')
+ meths.set_option_value('statusline', '%0@MyClickFunc@Clicky stuff%T %= %0@MyClickFunc@Clicky stuff%T', {})
command('vsplit')
screen:expect([[
^ │ |
@@ -394,38 +394,38 @@ describe('global statusline', function()
end)
it('win_move_statusline() can reduce cmdheight to 1', function()
- eq(1, meths.get_option('cmdheight'))
+ eq(1, meths.get_option_value('cmdheight', {}))
funcs.win_move_statusline(0, -1)
- eq(2, meths.get_option('cmdheight'))
+ eq(2, meths.get_option_value('cmdheight', {}))
funcs.win_move_statusline(0, -1)
- eq(3, meths.get_option('cmdheight'))
+ eq(3, meths.get_option_value('cmdheight', {}))
funcs.win_move_statusline(0, 1)
- eq(2, meths.get_option('cmdheight'))
+ eq(2, meths.get_option_value('cmdheight', {}))
funcs.win_move_statusline(0, 1)
- eq(1, meths.get_option('cmdheight'))
+ eq(1, meths.get_option_value('cmdheight', {}))
end)
it('mouse dragging can reduce cmdheight to 1', function()
command('set mouse=a')
meths.input_mouse('left', 'press', '', 0, 14, 10)
- eq(1, meths.get_option('cmdheight'))
+ eq(1, meths.get_option_value('cmdheight', {}))
meths.input_mouse('left', 'drag', '', 0, 13, 10)
- eq(2, meths.get_option('cmdheight'))
+ eq(2, meths.get_option_value('cmdheight', {}))
meths.input_mouse('left', 'drag', '', 0, 12, 10)
- eq(3, meths.get_option('cmdheight'))
+ eq(3, meths.get_option_value('cmdheight', {}))
meths.input_mouse('left', 'drag', '', 0, 13, 10)
- eq(2, meths.get_option('cmdheight'))
+ eq(2, meths.get_option_value('cmdheight', {}))
meths.input_mouse('left', 'drag', '', 0, 14, 10)
- eq(1, meths.get_option('cmdheight'))
+ eq(1, meths.get_option_value('cmdheight', {}))
meths.input_mouse('left', 'drag', '', 0, 15, 10)
- eq(1, meths.get_option('cmdheight'))
+ eq(1, meths.get_option_value('cmdheight', {}))
meths.input_mouse('left', 'drag', '', 0, 14, 10)
- eq(1, meths.get_option('cmdheight'))
+ eq(1, meths.get_option_value('cmdheight', {}))
end)
it('cmdline row is correct after setting cmdheight #20514', function()
command('botright split test/functional/fixtures/bigfile.txt')
- meths.set_option('cmdheight', 1)
+ meths.set_option_value('cmdheight', 1, {})
feed('L')
screen:expect([[
|
@@ -464,7 +464,7 @@ describe('global statusline', function()
{2:test/functional/fixtures/bigfile.txt 8,1 0%}|
|
]])
- meths.set_option('showtabline', 2)
+ meths.set_option_value('showtabline', 2, {})
screen:expect([[
{3: }{5:2}{3: t/f/f/bigfile.txt }{4: }|
|
@@ -483,7 +483,7 @@ describe('global statusline', function()
{2:test/functional/fixtures/bigfile.txt 8,1 0%}|
|
]])
- meths.set_option('cmdheight', 0)
+ meths.set_option_value('cmdheight', 0, {})
screen:expect([[
{3: }{5:2}{3: t/f/f/bigfile.txt }{4: }|
|
@@ -502,7 +502,7 @@ describe('global statusline', function()
^0007;<control>;Cc;0;BN;;;;;N;BELL;;;; |
{2:test/functional/fixtures/bigfile.txt 8,1 0%}|
]])
- meths.set_option('cmdheight', 1)
+ meths.set_option_value('cmdheight', 1, {})
screen:expect([[
{3: }{5:2}{3: t/f/f/bigfile.txt }{4: }|
|
@@ -526,8 +526,8 @@ end)
it('statusline does not crash if it has Arabic characters #19447', function()
clear()
- meths.set_option('statusline', 'غً')
- meths.set_option('laststatus', 2)
+ meths.set_option_value('statusline', 'غً', {})
+ meths.set_option_value('laststatus', 2, {})
command('redraw!')
assert_alive()
end)
diff --git a/test/functional/ui/title_spec.lua b/test/functional/ui/title_spec.lua
new file mode 100644
index 0000000000..2247d2e80f
--- /dev/null
+++ b/test/functional/ui/title_spec.lua
@@ -0,0 +1,138 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear = helpers.clear
+local command = helpers.command
+local curwin = helpers.curwin
+local eq = helpers.eq
+local exec_lua = helpers.exec_lua
+local feed = helpers.feed
+local funcs = helpers.funcs
+local meths = helpers.meths
+local is_os = helpers.is_os
+
+describe('title', function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new()
+ screen:attach()
+ end)
+
+ it('has correct default title with unnamed file', function()
+ local expected = '[No Name] - NVIM'
+ command('set title')
+ screen:expect(function()
+ eq(expected, screen.title)
+ end)
+ end)
+
+ it('has correct default title with named file', function()
+ local expected = (is_os('win') and 'myfile (C:\\mydir) - NVIM' or 'myfile (/mydir) - NVIM')
+ command('set title')
+ command(is_os('win') and 'file C:\\mydir\\myfile' or 'file /mydir/myfile')
+ screen:expect(function()
+ eq(expected, screen.title)
+ end)
+ end)
+
+ describe('is not changed by', function()
+ local file1 = is_os('win') and 'C:\\mydir\\myfile1' or '/mydir/myfile1'
+ local file2 = is_os('win') and 'C:\\mydir\\myfile2' or '/mydir/myfile2'
+ local expected = (is_os('win') and 'myfile1 (C:\\mydir) - NVIM' or 'myfile1 (/mydir) - NVIM')
+ local buf2
+
+ before_each(function()
+ command('edit '..file1)
+ buf2 = funcs.bufadd(file2)
+ command('set title')
+ end)
+
+ it('calling setbufvar() to set an option in a hidden buffer from i_CTRL-R', function()
+ command([[inoremap <F2> <C-R>=setbufvar(]]..buf2..[[, '&autoindent', 1) ? '' : ''<CR>]])
+ feed('i<F2><Esc>')
+ command('redraw!')
+ screen:expect(function()
+ eq(expected, screen.title)
+ end)
+ end)
+
+ it('an RPC call to nvim_set_option_value in a hidden buffer', function()
+ meths.set_option_value('autoindent', true, { buf = buf2 })
+ command('redraw!')
+ screen:expect(function()
+ eq(expected, screen.title)
+ end)
+ end)
+
+ it('a Lua callback calling nvim_set_option_value in a hidden buffer', function()
+ exec_lua(string.format([[
+ vim.schedule(function()
+ vim.api.nvim_set_option_value('autoindent', true, { buf = %d })
+ end)
+ ]], buf2))
+ command('redraw!')
+ screen:expect(function()
+ eq(expected, screen.title)
+ end)
+ end)
+
+ it('a Lua callback calling nvim_buf_call in a hidden buffer', function()
+ exec_lua(string.format([[
+ vim.schedule(function()
+ vim.api.nvim_buf_call(%d, function() end)
+ end)
+ ]], buf2))
+ command('redraw!')
+ screen:expect(function()
+ eq(expected, screen.title)
+ end)
+ end)
+
+ it('setting the buffer of another window using RPC', function()
+ local oldwin = curwin().id
+ command('split')
+ meths.win_set_buf(oldwin, buf2)
+ command('redraw!')
+ screen:expect(function()
+ eq(expected, screen.title)
+ end)
+ end)
+
+ it('setting the buffer of another window using Lua callback', function()
+ local oldwin = curwin().id
+ command('split')
+ exec_lua(string.format([[
+ vim.schedule(function()
+ vim.api.nvim_win_set_buf(%d, %d)
+ end)
+ ]], oldwin, buf2))
+ command('redraw!')
+ screen:expect(function()
+ eq(expected, screen.title)
+ end)
+ end)
+
+ it('creating a floating window using RPC', function()
+ meths.open_win(buf2, false, {
+ relative = 'editor', width = 5, height = 5, row = 0, col = 0,
+ })
+ command('redraw!')
+ screen:expect(function()
+ eq(expected, screen.title)
+ end)
+ end)
+
+ it('creating a floating window using Lua callback', function()
+ exec_lua(string.format([[
+ vim.api.nvim_open_win(%d, false, {
+ relative = 'editor', width = 5, height = 5, row = 0, col = 0,
+ })
+ ]], buf2))
+ command('redraw!')
+ screen:expect(function()
+ eq(expected, screen.title)
+ end)
+ end)
+ end)
+end)
diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua
index 50466c9473..0355c57b5a 100644
--- a/test/functional/ui/wildmode_spec.lua
+++ b/test/functional/ui/wildmode_spec.lua
@@ -367,12 +367,12 @@ describe("'wildmenu'", function()
}
-- Wildcharm? where we are going we aint't no need no wildcharm.
- eq(0, meths.get_option'wildcharm')
+ eq(0, meths.get_option_value('wildcharm', {}))
-- Don't mess the defaults yet (neovim is about backwards compatibility)
- eq(9, meths.get_option'wildchar')
+ eq(9, meths.get_option_value('wildchar', {}))
-- Lol what is cnoremap? Some say it can define mappings.
command 'set wildchar=0'
- eq(0, meths.get_option'wildchar')
+ eq(0, meths.get_option_value('wildchar', {}))
command 'cnoremap <f2> <c-z>'
feed(':syntax <f2>')
@@ -481,9 +481,9 @@ describe('command line completion', function()
end)
it('does not leak memory with <S-Tab> with wildmenu and only one match #19874', function()
- meths.set_option('wildmenu', true)
- meths.set_option('wildmode', 'full')
- meths.set_option('wildoptions', 'pum')
+ meths.set_option_value('wildmenu', true, {})
+ meths.set_option_value('wildmode', 'full', {})
+ meths.set_option_value('wildoptions', 'pum', {})
feed(':sign unpla<S-Tab>')
screen:expect([[
@@ -505,8 +505,8 @@ describe('command line completion', function()
end)
it('does not show matches with <S-Tab> without wildmenu with wildmode=full', function()
- meths.set_option('wildmenu', false)
- meths.set_option('wildmode', 'full')
+ meths.set_option_value('wildmenu', false, {})
+ meths.set_option_value('wildmode', 'full', {})
feed(':sign <S-Tab>')
screen:expect([[
@@ -519,8 +519,8 @@ describe('command line completion', function()
end)
it('shows matches with <S-Tab> without wildmenu with wildmode=list', function()
- meths.set_option('wildmenu', false)
- meths.set_option('wildmode', 'list')
+ meths.set_option_value('wildmenu', false, {})
+ meths.set_option_value('wildmode', 'list', {})
feed(':sign <S-Tab>')
screen:expect([[
diff --git a/test/functional/ui/winbar_spec.lua b/test/functional/ui/winbar_spec.lua
index 970f9c3d76..78bbcd3a63 100644
--- a/test/functional/ui/winbar_spec.lua
+++ b/test/functional/ui/winbar_spec.lua
@@ -31,7 +31,7 @@ describe('winbar', function()
[10] = {background = Screen.colors.LightGrey, underline = true},
[11] = {background = Screen.colors.LightGrey, underline = true, bold = true, foreground = Screen.colors.Magenta},
})
- meths.set_option('winbar', 'Set Up The Bars')
+ meths.set_option_value('winbar', 'Set Up The Bars', {})
end)
it('works', function()
@@ -206,7 +206,7 @@ describe('winbar', function()
insert [[
just some
random text]]
- meths.set_option('winbar', 'Hello, I am a ruler: %l,%c')
+ meths.set_option_value('winbar', 'Hello, I am a ruler: %l,%c', {})
screen:expect{grid=[[
{1:Hello, I am a ruler: 2,11 }|
just some |
@@ -450,7 +450,7 @@ describe('winbar', function()
|
|
]])
- eq(3, meths.get_option('cmdheight'))
+ eq(3, meths.get_option_value('cmdheight', {}))
meths.input_mouse('left', 'drag', '', 1, 11, 10)
screen:expect([[
@@ -468,7 +468,7 @@ describe('winbar', function()
{2:[No Name] }|
|
]])
- eq(1, meths.get_option('cmdheight'))
+ eq(1, meths.get_option_value('cmdheight', {}))
end)
it('properly equalizes window height for window-local value', function()
@@ -713,3 +713,26 @@ describe('local winbar with tabs', function()
]]}
end)
end)
+
+it('winbar works properly when redrawing is postponed #23534', function()
+ clear({args = {
+ '-c', 'set laststatus=2 lazyredraw',
+ '-c', 'setlocal statusline=(statusline) winbar=(winbar)',
+ '-c', 'call nvim_input(":<Esc>")',
+ }})
+ local screen = Screen.new(60, 6)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [0] = {foreground = Screen.colors.Blue, bold = true},
+ [1] = {bold = true},
+ [2] = {bold = true, reverse = true},
+ })
+ screen:expect([[
+ {1:(winbar) }|
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {2:(statusline) }|
+ |
+ ]])
+end)
diff --git a/test/functional/vimscript/api_functions_spec.lua b/test/functional/vimscript/api_functions_spec.lua
index dc591c3e0d..3404b06a55 100644
--- a/test/functional/vimscript/api_functions_spec.lua
+++ b/test/functional/vimscript/api_functions_spec.lua
@@ -32,8 +32,8 @@ describe('eval-API', function()
local err = exc_exec('call nvim_get_current_buf("foo")')
eq('Vim(call):E118: Too many arguments for function: nvim_get_current_buf', err)
- err = exc_exec('call nvim_set_option("hlsearch")')
- eq('Vim(call):E119: Not enough arguments for function: nvim_set_option', err)
+ err = exc_exec('call nvim_set_option_value("hlsearch")')
+ eq('Vim(call):E119: Not enough arguments for function: nvim_set_option_value', err)
err = exc_exec('call nvim_buf_set_lines(1, 0, -1, [], ["list"])')
eq('Vim(call):E5555: API call: Wrong type for argument 4 when calling nvim_buf_set_lines, expecting Boolean', err)
diff --git a/test/functional/vimscript/buf_functions_spec.lua b/test/functional/vimscript/buf_functions_spec.lua
index 7a54f479e0..2a5720fbd7 100644
--- a/test/functional/vimscript/buf_functions_spec.lua
+++ b/test/functional/vimscript/buf_functions_spec.lua
@@ -9,7 +9,6 @@ local meths = helpers.meths
local command = helpers.command
local exc_exec = helpers.exc_exec
local bufmeths = helpers.bufmeths
-local winmeths = helpers.winmeths
local curbufmeths = helpers.curbufmeths
local curwinmeths = helpers.curwinmeths
local curtabmeths = helpers.curtabmeths
@@ -189,7 +188,7 @@ describe('getbufline() function', function()
eq({}, funcs.getbufline(1, -1, 9999))
end)
it('returns expected lines', function()
- meths.set_option('hidden', true)
+ meths.set_option_value('hidden', true, {})
command('file ' .. fname)
curbufmeths.set_lines(0, 1, false, {'foo\0', '\0bar', 'baz'})
command('edit ' .. fname2)
@@ -269,24 +268,25 @@ describe('setbufvar() function', function()
end)
it('may set options, including window-local and global values', function()
local buf1 = meths.get_current_buf()
- eq(false, curwinmeths.get_option('number'))
+ eq(false, meths.get_option_value('number', {}))
command('split')
command('new')
eq(2, bufmeths.get_number(curwinmeths.get_buf()))
funcs.setbufvar(1, '&number', true)
local windows = curtabmeths.list_wins()
- eq(false, winmeths.get_option(windows[1], 'number'))
- eq(true, winmeths.get_option(windows[2], 'number'))
- eq(false, winmeths.get_option(windows[3], 'number'))
- eq(false, winmeths.get_option(meths.get_current_win(), 'number'))
+ eq(false, meths.get_option_value('number', {win=windows[1].id}))
+ eq(true, meths.get_option_value('number', {win=windows[2].id}))
+ eq(false, meths.get_option_value('number', {win=windows[3].id}))
+ eq(false, meths.get_option_value('number', {win=meths.get_current_win().id}))
- eq(true, meths.get_option('hidden'))
+
+ eq(true, meths.get_option_value('hidden', {}))
funcs.setbufvar(1, '&hidden', 0)
- eq(false, meths.get_option('hidden'))
+ eq(false, meths.get_option_value('hidden', {}))
- eq(false, bufmeths.get_option(buf1, 'autoindent'))
+ eq(false, meths.get_option_value('autoindent', {buf=buf1.id}))
funcs.setbufvar(1, '&autoindent', true)
- eq(true, bufmeths.get_option(buf1, 'autoindent'))
+ eq(true, meths.get_option_value('autoindent', {buf=buf1.id}))
eq('Vim(call):E355: Unknown option: xxx',
exc_exec('call setbufvar(1, "&xxx", 0)'))
end)
diff --git a/test/functional/vimscript/input_spec.lua b/test/functional/vimscript/input_spec.lua
index d1643a799a..bd9f7e5381 100644
--- a/test/functional/vimscript/input_spec.lua
+++ b/test/functional/vimscript/input_spec.lua
@@ -452,8 +452,8 @@ end)
describe('confirm()', function()
-- oldtest: Test_confirm()
it('works', function()
- meths.set_option('more', false) -- Avoid hit-enter prompt
- meths.set_option('laststatus', 2)
+ meths.set_option_value('more', false, {}) -- Avoid hit-enter prompt
+ meths.set_option_value('laststatus', 2, {})
-- screen:expect() calls are needed to avoid feeding input too early
screen:expect({any = '%[No Name%]'})
diff --git a/test/functional/vimscript/json_functions_spec.lua b/test/functional/vimscript/json_functions_spec.lua
index 70d0934756..a9dab8431c 100644
--- a/test/functional/vimscript/json_functions_spec.lua
+++ b/test/functional/vimscript/json_functions_spec.lua
@@ -754,7 +754,7 @@ describe('json_encode() function', function()
end)
it('ignores improper values in &isprint', function()
- meths.set_option('isprint', '1')
+ meths.set_option_value('isprint', '1', {})
eq(1, eval('"\1" =~# "\\\\p"'))
eq('"\\u0001"', funcs.json_encode('\1'))
end)
diff --git a/test/functional/vimscript/system_spec.lua b/test/functional/vimscript/system_spec.lua
index 130d5d81fa..762e8877ce 100644
--- a/test/functional/vimscript/system_spec.lua
+++ b/test/functional/vimscript/system_spec.lua
@@ -210,8 +210,8 @@ describe('system()', function()
end)
it('prints verbose information', function()
- nvim('set_option', 'shell', 'fake_shell')
- nvim('set_option', 'shellcmdflag', 'cmdflag')
+ nvim('set_option_value', 'shell', 'fake_shell', {})
+ nvim('set_option_value', 'shellcmdflag', 'cmdflag', {})
screen:try_resize(72, 14)
feed(':4verbose echo system("echo hi")<cr>')
diff --git a/test/old/testdir/test_charsearch.vim b/test/old/testdir/test_charsearch.vim
index 8d6b405743..084d4f0a22 100644
--- a/test/old/testdir/test_charsearch.vim
+++ b/test/old/testdir/test_charsearch.vim
@@ -38,6 +38,8 @@ func Test_charsearch()
" clear the character search
call setcharsearch({'char' : ''})
call assert_equal('', getcharsearch().char)
+ call assert_beeps('normal ;')
+ call assert_beeps('normal ,')
call assert_fails("call setcharsearch([])", 'E1206:')
enew!
diff --git a/test/old/testdir/test_charsearch_utf8.vim b/test/old/testdir/test_charsearch_utf8.vim
index 82a807ac5b..843edbb514 100644
--- a/test/old/testdir/test_charsearch_utf8.vim
+++ b/test/old/testdir/test_charsearch_utf8.vim
@@ -13,6 +13,13 @@ func Test_search_cmds()
call assert_equal([0, 1, 43, 0], getpos('.'))
normal! ,
call assert_equal([0, 1, 28, 0], getpos('.'))
+ call assert_equal('最', getcharsearch().char)
+ call setcharsearch({'char' : ''})
+ call assert_equal('', getcharsearch().char)
+ call assert_beeps('normal ;')
+ call assert_equal([0, 1, 28, 0], getpos('.'))
+ call assert_beeps('normal ,')
+ call assert_equal([0, 1, 28, 0], getpos('.'))
bw!
endfunc
diff --git a/test/old/testdir/test_cmdline.vim b/test/old/testdir/test_cmdline.vim
index 9ed49b44c0..96a30a1dd5 100644
--- a/test/old/testdir/test_cmdline.vim
+++ b/test/old/testdir/test_cmdline.vim
@@ -719,7 +719,7 @@ endfunc
func Test_shellcmd_completion()
let save_path = $PATH
- call mkdir('Xpathdir/Xpathsubdir', 'p')
+ call mkdir('Xpathdir/Xpathsubdir', 'pR')
call writefile([''], 'Xpathdir/Xfile.exe')
call setfperm('Xpathdir/Xfile.exe', 'rwx------')
@@ -735,17 +735,15 @@ func Test_shellcmd_completion()
call insert(expected, 'Xfile.exe')
call assert_equal(expected, actual)
- call delete('Xpathdir', 'rf')
let $PATH = save_path
endfunc
func Test_expand_star_star()
- call mkdir('a/b', 'p')
- call writefile(['asdfasdf'], 'a/b/fileXname')
- call feedkeys(":find **/fileXname\<Tab>\<CR>", 'xt')
- call assert_equal('find a/b/fileXname', @:)
+ call mkdir('a/b/c', 'pR')
+ call writefile(['asdfasdf'], 'a/b/c/fileXname')
+ call feedkeys(":find a/**/fileXname\<Tab>\<CR>", 'xt')
+ call assert_equal('find a/b/c/fileXname', @:)
bwipe!
- call delete('a', 'rf')
endfunc
func Test_cmdline_paste()
diff --git a/test/old/testdir/test_cmdwin.vim b/test/old/testdir/test_cmdwin.vim
new file mode 100644
index 0000000000..f948d46be1
--- /dev/null
+++ b/test/old/testdir/test_cmdwin.vim
@@ -0,0 +1,67 @@
+" Tests for editing the command line.
+
+source check.vim
+source screendump.vim
+
+
+func Test_cant_open_cmdwin_in_cmdwin()
+ try
+ call feedkeys("q:q::q\<CR>", "x!")
+ catch
+ let caught = v:exception
+ endtry
+ call assert_match('E1292:', caught)
+endfunc
+
+func Test_cmdwin_virtual_edit()
+ enew!
+ set ve=all cpo+=$
+ silent normal q/s
+
+ set ve= cpo-=$
+endfunc
+
+" Check that a :normal command can be used to stop Visual mode without side
+" effects.
+func Test_normal_escape()
+ call feedkeys("q:i\" foo\<Esc>:normal! \<C-V>\<Esc>\<CR>:\" bar\<CR>", 'ntx')
+ call assert_equal('" bar', @:)
+endfunc
+
+" This was using a pointer to a freed buffer
+func Test_cmdwin_freed_buffer_ptr()
+ " this does not work on MS-Windows because renaming an open file fails
+ CheckNotMSWindows
+
+ au BufEnter * next 0| file
+ edit 0
+ silent! norm q/
+
+ au! BufEnter
+ bwipe!
+endfunc
+
+" This was resulting in a window with negative width.
+" The test doesn't reproduce the illegal memory access though...
+func Test_cmdwin_split_often()
+ let lines = &lines
+ let columns = &columns
+ set t_WS=
+
+ try
+ " set encoding=iso8859
+ set ruler
+ winsize 0 0
+ noremap 0 H
+ sil norm 0000000q:
+ catch /E36:/
+ endtry
+
+ bwipe!
+ set encoding=utf8
+ let &lines = lines
+ let &columns = columns
+endfunc
+
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_display.vim b/test/old/testdir/test_display.vim
index f27a8362a9..e007b6f741 100644
--- a/test/old/testdir/test_display.vim
+++ b/test/old/testdir/test_display.vim
@@ -482,9 +482,9 @@ func Test_display_long_lastline()
CheckScreendump
let lines =<< trim END
- set display=lastline
+ set display=lastline smoothscroll scrolloff=0
call setline(1, [
- \'aaaaa'->repeat(100),
+ \'aaaaa'->repeat(150),
\'bbbbb '->repeat(7) .. 'ccccc '->repeat(7) .. 'ddddd '->repeat(7)
\])
END
@@ -492,11 +492,56 @@ func Test_display_long_lastline()
call writefile(lines, 'XdispLongline', 'D')
let buf = RunVimInTerminal('-S XdispLongline', #{rows: 14, cols: 35})
- call term_sendkeys(buf, "482|")
+ call term_sendkeys(buf, "736|")
call VerifyScreenDump(buf, 'Test_display_long_line_1', {})
+
+ " The correct part of the last line is moved into view.
call term_sendkeys(buf, "D")
call VerifyScreenDump(buf, 'Test_display_long_line_2', {})
+ " "w_skipcol" does not change because the topline is still long enough
+ " to maintain the current skipcol.
+ call term_sendkeys(buf, "g04l11gkD")
+ call VerifyScreenDump(buf, 'Test_display_long_line_3', {})
+
+ " "w_skipcol" is reset to bring the entire topline into view because
+ " the line length is now smaller than the current skipcol + marker.
+ call term_sendkeys(buf, "x")
+ call VerifyScreenDump(buf, 'Test_display_long_line_4', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+" Moving the cursor to a line that doesn't fit in the window should show
+" correctly.
+func Test_display_cursor_long_line()
+ CheckScreendump
+
+ let lines =<< trim END
+ call setline(1, ['a', 'b ' .. 'bbbbb'->repeat(150), 'c'])
+ norm $j
+ END
+
+ call writefile(lines, 'XdispCursorLongline', 'D')
+ let buf = RunVimInTerminal('-S XdispCursorLongline', #{rows: 8})
+
+ call VerifyScreenDump(buf, 'Test_display_cursor_long_line_1', {})
+
+ " FIXME: moving the cursor above the topline does not set w_skipcol
+ " correctly with cpo+=n and zero scrolloff (curs_columns() extra == 1).
+ call term_sendkeys(buf, ":set number cpo+=n scrolloff=0\<CR>")
+ call term_sendkeys(buf, '$0')
+ call VerifyScreenDump(buf, 'Test_display_cursor_long_line_2', {})
+
+ " Going to the start of the line with "b" did not set w_skipcol correctly
+ " with 'smoothscroll'.
+ call term_sendkeys(buf, ":set smoothscroll\<CR>")
+ call term_sendkeys(buf, '$b')
+ call VerifyScreenDump(buf, 'Test_display_cursor_long_line_3', {})
+ " Same for "ge".
+ call term_sendkeys(buf, '$ge')
+ call VerifyScreenDump(buf, 'Test_display_cursor_long_line_4', {})
+
call StopVimInTerminal(buf)
endfunc
diff --git a/test/old/testdir/test_ex_mode.vim b/test/old/testdir/test_ex_mode.vim
index b30dce8630..3332bc6ab9 100644
--- a/test/old/testdir/test_ex_mode.vim
+++ b/test/old/testdir/test_ex_mode.vim
@@ -218,9 +218,9 @@ func Test_Ex_echo_backslash()
let bsl = '\\\\'
let bsl2 = '\\\'
call assert_fails('call feedkeys("Qecho " .. bsl .. "\nvisual\n", "xt")',
- \ "E15: Invalid expression: \\\\")
+ \ 'E15: Invalid expression: "\\"')
call assert_fails('call feedkeys("Qecho " .. bsl2 .. "\nm\nvisual\n", "xt")',
- \ "E15: Invalid expression: \\\nm")
+ \ "E15: Invalid expression: \"\\\nm\"")
endfunc
func Test_ex_mode_errors()
diff --git a/test/old/testdir/test_exit.vim b/test/old/testdir/test_exit.vim
index 6dbfb7047c..93e55ce575 100644
--- a/test/old/testdir/test_exit.vim
+++ b/test/old/testdir/test_exit.vim
@@ -81,6 +81,18 @@ func Test_exiting()
\ readfile('Xtestout'))
endif
call delete('Xtestout')
+
+ " ExitPre autocommand also executed on :wqall
+ let after =<< trim [CODE]
+ au QuitPre * call writefile(["QuitPre"], "Xtestout", "a")
+ au ExitPre * call writefile(["ExitPre"], "Xtestout", "a")
+ wqall
+ [CODE]
+
+ if RunVim([], after, '')
+ call assert_equal(['QuitPre', 'ExitPre'], readfile('Xtestout'))
+ endif
+ call delete('Xtestout')
endfunc
" Test for getting the Vim exit code from v:exiting
diff --git a/test/old/testdir/test_expr.vim b/test/old/testdir/test_expr.vim
index 9e089d50b8..4cb8da8c74 100644
--- a/test/old/testdir/test_expr.vim
+++ b/test/old/testdir/test_expr.vim
@@ -154,6 +154,9 @@ func Test_strcharpart()
call assert_equal('edit', "editor"[-10 : 3])
END
call CheckLegacyAndVim9Success(lines)
+
+ call assert_fails('call strcharpart("", 0, 0, {})', ['E728:', 'E728:'])
+ call assert_fails('call strcharpart("", 0, 0, -1)', ['E1023:', 'E1023:'])
endfunc
func Test_getreg_empty_list()
diff --git a/test/old/testdir/test_filetype.vim b/test/old/testdir/test_filetype.vim
index 2d7a24090f..2858bf1add 100644
--- a/test/old/testdir/test_filetype.vim
+++ b/test/old/testdir/test_filetype.vim
@@ -305,6 +305,7 @@ let s:filename_checks = {
\ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', '.prettierrc', '.firebaserc', '.stylelintrc', 'file.slnf'],
\ 'json5': ['file.json5'],
\ 'jsonc': ['file.jsonc', '.babelrc', '.eslintrc', '.jsfmtrc', '.jshintrc', '.hintrc', '.swrc', 'jsconfig.json', 'tsconfig.json', 'tsconfig.test.json', 'tsconfig-test.json'],
+ \ 'jsonl': ['file.jsonl'],
\ 'jsonnet': ['file.jsonnet', 'file.libsonnet'],
\ 'jsp': ['file.jsp'],
\ 'julia': ['file.jl'],
@@ -564,7 +565,7 @@ let s:filename_checks = {
\ 'spice': ['file.sp', 'file.spice'],
\ 'spup': ['file.speedup', 'file.spdata', 'file.spd'],
\ 'spyce': ['file.spy', 'file.spi'],
- \ 'sql': ['file.tyb', 'file.typ', 'file.tyc', 'file.pkb', 'file.pks'],
+ \ 'sql': ['file.tyb', 'file.tyc', 'file.pkb', 'file.pks'],
\ 'sqlj': ['file.sqlj'],
\ 'prql': ['file.prql'],
\ 'sqr': ['file.sqr', 'file.sqi'],
@@ -638,6 +639,7 @@ let s:filename_checks = {
\ 'upstreamdat': ['upstream.dat', 'UPSTREAM.DAT', 'upstream.file.dat', 'UPSTREAM.FILE.DAT', 'file.upstream.dat', 'FILE.UPSTREAM.DAT'],
\ 'upstreaminstalllog': ['upstreaminstall.log', 'UPSTREAMINSTALL.LOG', 'upstreaminstall.file.log', 'UPSTREAMINSTALL.FILE.LOG', 'file.upstreaminstall.log', 'FILE.UPSTREAMINSTALL.LOG'],
\ 'upstreamlog': ['fdrupstream.log', 'upstream.log', 'UPSTREAM.LOG', 'upstream.file.log', 'UPSTREAM.FILE.LOG', 'file.upstream.log', 'FILE.UPSTREAM.LOG', 'UPSTREAM-file.log', 'UPSTREAM-FILE.LOG'],
+ \ 'usd': ['file.usda', 'file.usd'],
\ 'usserverlog': ['usserver.log', 'USSERVER.LOG', 'usserver.file.log', 'USSERVER.FILE.LOG', 'file.usserver.log', 'FILE.USSERVER.LOG'],
\ 'usw2kagtlog': ['usw2kagt.log', 'USW2KAGT.LOG', 'usw2kagt.file.log', 'USW2KAGT.FILE.LOG', 'file.usw2kagt.log', 'FILE.USW2KAGT.LOG'],
\ 'vala': ['file.vala'],
@@ -708,19 +710,20 @@ func CheckItems(checks)
for i in range(0, len(names) - 1)
new
try
- exe 'edit ' . fnameescape(names[i])
+ exe 'edit ' .. fnameescape(names[i])
catch
- call assert_report('cannot edit "' . names[i] . '": ' . v:exception)
+ call assert_report('cannot edit "' .. names[i] .. '": ' .. v:exception)
endtry
if &filetype == '' && &readonly
" File exists but not able to edit it (permission denied)
else
let expected = ft == 'none' ? '' : ft
- call assert_equal(expected, &filetype, 'with file name: ' . names[i])
+ call assert_equal(expected, &filetype, 'with file name: ' .. names[i])
endif
bwipe!
endfor
endfor
+
set swapfile&
endfunc
@@ -2047,4 +2050,35 @@ func Test_lsl_file()
filetype off
endfunc
+func Test_typ_file()
+ filetype on
+
+ " SQL type file
+
+ call writefile(['CASE = LOWER'], 'Xfile.typ', 'D')
+ split Xfile.typ
+ call assert_equal('sql', &filetype)
+ bwipe!
+
+ call writefile(['TYPE foo'], 'Xfile.typ')
+ split Xfile.typ
+ call assert_equal('sql', &filetype)
+ bwipe!
+
+ " typst document
+
+ call writefile(['this is a fallback'], 'Xfile.typ')
+ split Xfile.typ
+ call assert_equal('typst', &filetype)
+ bwipe!
+
+ let g:filetype_typ = 'typst'
+ split test.typ
+ call assert_equal('typst', &filetype)
+ bwipe!
+ unlet g:filetype_typ
+
+ filetype off
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_functions.vim b/test/old/testdir/test_functions.vim
index b934f7fac2..41a8610893 100644
--- a/test/old/testdir/test_functions.vim
+++ b/test/old/testdir/test_functions.vim
@@ -1096,6 +1096,8 @@ func Test_byteidx()
" error cases
call assert_fails("call byteidx([], 0)", 'E730:')
call assert_fails("call byteidx('abc', [])", 'E745:')
+ call assert_fails("call byteidx('abc', 0, {})", ['E728:', 'E728:'])
+ call assert_fails("call byteidx('abc', 0, -1)", ['E1023:', 'E1023:'])
endfunc
" Test for byteidxcomp() using a character index
@@ -1135,6 +1137,8 @@ func Test_byteidxcomp()
" error cases
call assert_fails("call byteidxcomp([], 0)", 'E730:')
call assert_fails("call byteidxcomp('abc', [])", 'E745:')
+ call assert_fails("call byteidxcomp('abc', 0, {})", ['E728:', 'E728:'])
+ call assert_fails("call byteidxcomp('abc', 0, -1)", ['E1023:', 'E1023:'])
endfunc
" Test for byteidx() using a UTF-16 index
diff --git a/test/old/testdir/test_gf.vim b/test/old/testdir/test_gf.vim
index f09dbd72ce..9824c8276e 100644
--- a/test/old/testdir/test_gf.vim
+++ b/test/old/testdir/test_gf.vim
@@ -300,4 +300,65 @@ func Test_gf_subdirs_wildcard()
set path&
endfunc
+" Test for 'switchbuf' with gf and gF commands
+func Test_gf_switchbuf()
+ call writefile(repeat(["aaa"], 10), "Xtest1", 'D')
+ edit Xtest1
+ new
+ call setline(1, ['Xtest1'])
+
+ " Test for 'useopen'
+ set switchbuf=useopen
+ call cursor(1, 1)
+ exe "normal \<C-W>f"
+ call assert_equal([2, 2], [winnr(), winnr('$')])
+ close
+
+ " If the file is opened in another tabpage, then it should not be considered
+ tabedit Xtest1
+ tabfirst
+ exe "normal \<C-W>f"
+ call assert_equal([1, 2], [winnr(), winnr('$')])
+ call assert_equal([1, 2], [tabpagenr(), tabpagenr('$')])
+ close
+
+ " Test for 'usetab'
+ set switchbuf=usetab
+ exe "normal \<C-W>f"
+ call assert_equal([1, 1], [winnr(), winnr('$')])
+ call assert_equal([2, 2], [tabpagenr(), tabpagenr('$')])
+ %bw!
+
+ " Test for CTRL-W_F with 'useopen'
+ set isfname-=:
+ call setline(1, ['Xtest1:5'])
+ set switchbuf=useopen
+ split +1 Xtest1
+ wincmd b
+ exe "normal \<C-W>F"
+ call assert_equal([1, 2], [winnr(), winnr('$')])
+ call assert_equal(5, line('.'))
+ close
+
+ " If the file is opened in another tabpage, then it should not be considered
+ tabedit +1 Xtest1
+ tabfirst
+ exe "normal \<C-W>F"
+ call assert_equal([1, 2], [winnr(), winnr('$')])
+ call assert_equal(5, line('.'))
+ call assert_equal([1, 2], [tabpagenr(), tabpagenr('$')])
+ close
+
+ " Test for CTRL_W_F with 'usetab'
+ set switchbuf=usetab
+ exe "normal \<C-W>F"
+ call assert_equal([2, 2], [tabpagenr(), tabpagenr('$')])
+ call assert_equal([1, 1], [winnr(), winnr('$')])
+ call assert_equal(5, line('.'))
+
+ set switchbuf=
+ set isfname&
+ %bw!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_mapping.vim b/test/old/testdir/test_mapping.vim
index e25c3c333e..8c957d4665 100644
--- a/test/old/testdir/test_mapping.vim
+++ b/test/old/testdir/test_mapping.vim
@@ -3,6 +3,7 @@
source shared.vim
source check.vim
source screendump.vim
+source term_util.vim
func Test_abbreviation()
" abbreviation with 0x80 should work
@@ -968,6 +969,469 @@ func Test_map_cpo_special_keycode()
mapclear!
endfunc
+" Test for <Cmd> key in maps to execute commands
+func Test_map_cmdkey()
+ new
+
+ " Error cases
+ let x = 0
+ noremap <F3> <Cmd><Cmd>let x = 1<CR>
+ call assert_fails('call feedkeys("\<F3>", "xt")', 'E1136:')
+ call assert_equal(0, x)
+
+ noremap <F3> <Cmd>let x = 3
+ call assert_fails('call feedkeys("\<F3>", "xt!")', 'E1255:')
+ call assert_equal(0, x)
+
+ " works in various modes and sees the correct mode()
+ noremap <F3> <Cmd>let m = mode(1)<CR>
+ noremap! <F3> <Cmd>let m = mode(1)<CR>
+
+ " normal mode
+ call feedkeys("\<F3>", 'xt')
+ call assert_equal('n', m)
+
+ " visual mode
+ call feedkeys("v\<F3>", 'xt!')
+ call assert_equal('v', m)
+ " shouldn't leave the visual mode
+ call assert_equal('v', mode(1))
+ call feedkeys("\<Esc>", 'xt')
+ call assert_equal('n', mode(1))
+
+ " visual mapping in select mode
+ call feedkeys("gh\<F3>", 'xt!')
+ call assert_equal('v', m)
+ " shouldn't leave select mode
+ call assert_equal('s', mode(1))
+ call feedkeys("\<Esc>", 'xt')
+ call assert_equal('n', mode(1))
+
+ " select mode mapping
+ snoremap <F3> <Cmd>let m = mode(1)<cr>
+ call feedkeys("gh\<F3>", 'xt!')
+ call assert_equal('s', m)
+ " shouldn't leave select mode
+ call assert_equal('s', mode(1))
+ call feedkeys("\<Esc>", 'xt')
+ call assert_equal('n', mode(1))
+
+ " operator-pending mode
+ call feedkeys("d\<F3>", 'xt!')
+ call assert_equal('no', m)
+ " leaves the operator-pending mode
+ call assert_equal('n', mode(1))
+
+ " insert mode
+ call feedkeys("i\<F3>abc", 'xt')
+ call assert_equal('i', m)
+ call assert_equal('abc', getline('.'))
+
+ " replace mode
+ call feedkeys("0R\<F3>two", 'xt')
+ call assert_equal('R', m)
+ call assert_equal('two', getline('.'))
+
+ " virtual replace mode
+ call setline('.', "one\ttwo")
+ call feedkeys("4|gR\<F3>xxx", 'xt')
+ call assert_equal('Rv', m)
+ call assert_equal("onexxx\ttwo", getline('.'))
+
+ " cmdline mode
+ call feedkeys(":\<F3>\"xxx\<CR>", 'xt!')
+ call assert_equal('c', m)
+ call assert_equal('"xxx', @:)
+
+ " terminal mode
+ if CanRunVimInTerminal()
+ tnoremap <F3> <Cmd>let m = mode(1)<CR>
+ let buf = Run_shell_in_terminal({})
+ call feedkeys("\<F3>", 'xt')
+ call assert_equal('t', m)
+ call assert_equal('t', mode(1))
+ call StopShellInTerminal(buf)
+ call TermWait(buf)
+ close!
+ tunmap <F3>
+ endif
+
+ " invoke cmdline mode recursively
+ noremap! <F2> <Cmd>norm! :foo<CR>
+ %d
+ call setline(1, ['some short lines', 'of test text'])
+ call feedkeys(":bar\<F2>x\<C-B>\"\r", 'xt')
+ call assert_equal('"barx', @:)
+ unmap! <F2>
+
+ " test for calling a <SID> function
+ let lines =<< trim END
+ map <F2> <Cmd>call <SID>do_it()<CR>
+ func s:do_it()
+ let g:x = 32
+ endfunc
+ END
+ call writefile(lines, 'Xscript')
+ source Xscript
+ call feedkeys("\<F2>", 'xt')
+ call assert_equal(32, g:x)
+ call delete('Xscript')
+
+ unmap <F3>
+ unmap! <F3>
+ %bw!
+endfunc
+
+" text object enters visual mode
+func TextObj()
+ if mode() !=# "v"
+ normal! v
+ end
+ call cursor(1, 3)
+ normal! o
+ call cursor(2, 4)
+endfunc
+
+func s:cmdmap(lhs, rhs)
+ exe 'noremap ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
+ exe 'noremap! ' .. a:lhs .. ' <Cmd>' .. a:rhs .. '<CR>'
+endfunc
+
+func s:cmdunmap(lhs)
+ exe 'unmap ' .. a:lhs
+ exe 'unmap! ' .. a:lhs
+endfunc
+
+" Map various <Fx> keys used by the <Cmd> key tests
+func s:setupMaps()
+ call s:cmdmap('<F3>', 'let m = mode(1)')
+ call s:cmdmap('<F4>', 'normal! ww')
+ call s:cmdmap('<F5>', 'normal! "ay')
+ call s:cmdmap('<F6>', 'throw "very error"')
+ call s:cmdmap('<F7>', 'call TextObj()')
+ call s:cmdmap('<F8>', 'startinsert')
+ call s:cmdmap('<F9>', 'stopinsert')
+endfunc
+
+" Remove the mappings setup by setupMaps()
+func s:cleanupMaps()
+ call s:cmdunmap('<F3>')
+ call s:cmdunmap('<F4>')
+ call s:cmdunmap('<F5>')
+ call s:cmdunmap('<F6>')
+ call s:cmdunmap('<F7>')
+ call s:cmdunmap('<F8>')
+ call s:cmdunmap('<F9>')
+endfunc
+
+" Test for <Cmd> mapping in normal mode
+func Test_map_cmdkey_normal_mode()
+ new
+ call s:setupMaps()
+
+ " check v:count and v:register works
+ call s:cmdmap('<F2>', 'let s = [mode(1), v:count, v:register]')
+ call feedkeys("\<F2>", 'xt')
+ call assert_equal(['n', 0, '"'], s)
+ call feedkeys("7\<F2>", 'xt')
+ call assert_equal(['n', 7, '"'], s)
+ call feedkeys("\"e\<F2>", 'xt')
+ call assert_equal(['n', 0, 'e'], s)
+ call feedkeys("5\"k\<F2>", 'xt')
+ call assert_equal(['n', 5, 'k'], s)
+ call s:cmdunmap('<F2>')
+
+ call setline(1, ['some short lines', 'of test text'])
+ call feedkeys("\<F7>y", 'xt')
+ call assert_equal("me short lines\nof t", @")
+ call assert_equal('v', getregtype('"'))
+ call assert_equal([0, 1, 3, 0], getpos("'<"))
+ call assert_equal([0, 2, 4, 0], getpos("'>"))
+
+ " startinsert
+ %d
+ call feedkeys("\<F8>abc", 'xt')
+ call assert_equal('abc', getline(1))
+
+ " feedkeys are not executed immediately
+ noremap ,a <Cmd>call feedkeys("aalpha") \| let g:a = getline(2)<CR>
+ %d
+ call setline(1, ['some short lines', 'of test text'])
+ call cursor(2, 3)
+ call feedkeys(",a\<F3>", 'xt')
+ call assert_equal('of test text', g:a)
+ call assert_equal('n', m)
+ call assert_equal(['some short lines', 'of alphatest text'], getline(1, '$'))
+ nunmap ,a
+
+ " feedkeys(..., 'x') is executed immediately, but insert mode is aborted
+ noremap ,b <Cmd>call feedkeys("abeta", 'x') \| let g:b = getline(2)<CR>
+ call feedkeys(",b\<F3>", 'xt')
+ call assert_equal('n', m)
+ call assert_equal('of alphabetatest text', g:b)
+ nunmap ,b
+
+ call s:cleanupMaps()
+ %bw!
+endfunc
+
+" Test for <Cmd> mapping with the :normal command
+func Test_map_cmdkey_normal_cmd()
+ new
+ noremap ,x <Cmd>call append(1, "xx") \| call append(1, "aa")<CR>
+ noremap ,f <Cmd>nosuchcommand<CR>
+ noremap ,e <Cmd>throw "very error" \| call append(1, "yy")<CR>
+ noremap ,m <Cmd>echoerr "The message." \| call append(1, "zz")<CR>
+ noremap ,w <Cmd>for i in range(5) \| if i==1 \| echoerr "Err" \| endif \| call append(1, i) \| endfor<CR>
+
+ call setline(1, ['some short lines', 'of test text'])
+ exe "norm ,x\r"
+ call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
+
+ call assert_fails('norm ,f', 'E492:')
+ call assert_fails('norm ,e', 'very error')
+ call assert_fails('norm ,m', 'The message.')
+ call assert_equal(['some short lines', 'aa', 'xx', 'of test text'], getline(1, '$'))
+
+ %d
+ let caught_err = 0
+ try
+ exe "normal ,w"
+ catch /Vim(echoerr):Err/
+ let caught_err = 1
+ endtry
+ call assert_equal(1, caught_err)
+ call assert_equal(['', '0'], getline(1, '$'))
+
+ %d
+ call assert_fails('normal ,w', 'Err')
+ call assert_equal(['', '4', '3', '2' ,'1', '0'], getline(1, '$'))
+ call assert_equal(1, line('.'))
+
+ nunmap ,x
+ nunmap ,f
+ nunmap ,e
+ nunmap ,m
+ nunmap ,w
+ %bw!
+endfunc
+
+" Test for <Cmd> mapping in visual mode
+func Test_map_cmdkey_visual_mode()
+ new
+ set showmode
+ call s:setupMaps()
+
+ call setline(1, ['some short lines', 'of test text'])
+ call feedkeys("v\<F4>", 'xt!')
+ call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')])
+
+ " can invoke an opeartor, ending the visual mode
+ let @a = ''
+ call feedkeys("\<F5>", 'xt!')
+ call assert_equal('n', mode(1))
+ call assert_equal('some short l', @a)
+
+ " error doesn't interrupt visual mode
+ call assert_fails('call feedkeys("ggvw\<F6>", "xt!")', 'E605:')
+ call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
+ call feedkeys("\<F7>", 'xt!')
+ call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
+
+ " startinsert gives "-- (insert) VISUAL --" mode
+ call feedkeys("\<F8>", 'xt!')
+ call assert_equal(['v', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
+ redraw!
+ call assert_match('^-- (insert) VISUAL --', Screenline(&lines))
+ call feedkeys("\<Esc>new ", 'x')
+ call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
+
+ call s:cleanupMaps()
+ set showmode&
+ %bw!
+endfunc
+
+" Test for <Cmd> mapping in select mode
+func Test_map_cmdkey_select_mode()
+ new
+ set showmode
+ call s:setupMaps()
+
+ snoremap <F1> <cmd>throw "very error"<CR>
+ snoremap <F2> <cmd>normal! <c-g>"by<CR>
+ call setline(1, ['some short lines', 'of test text'])
+
+ call feedkeys("gh\<F4>", "xt!")
+ call assert_equal(['s', 1, 12], [mode(1), col('v'), col('.')])
+ redraw!
+ call assert_match('^-- SELECT --', Screenline(&lines))
+
+ " visual mapping in select mode restarts select mode after operator
+ let @a = ''
+ call feedkeys("\<F5>", 'xt!')
+ call assert_equal('s', mode(1))
+ call assert_equal('some short l', @a)
+
+ " select mode mapping works, and does not restart select mode
+ let @b = ''
+ call feedkeys("\<F2>", 'xt!')
+ call assert_equal('n', mode(1))
+ call assert_equal('some short l', @b)
+
+ " error doesn't interrupt temporary visual mode
+ call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F6>", "xt!")', 'E605:')
+ redraw!
+ call assert_match('^-- VISUAL --', Screenline(&lines))
+ " quirk: restoration of select mode is not performed
+ call assert_equal(['v', 1, 6], [mode(1), col('v'), col('.')])
+
+ " error doesn't interrupt select mode
+ call assert_fails('call feedkeys("\<Esc>ggvw\<C-G>\<F1>", "xt!")', 'E605:')
+ redraw!
+ call assert_match('^-- SELECT --', Screenline(&lines))
+ call assert_equal(['s', 1, 6], [mode(1), col('v'), col('.')])
+
+ call feedkeys("\<F7>", 'xt!')
+ redraw!
+ call assert_match('^-- SELECT --', Screenline(&lines))
+ call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
+
+ " startinsert gives "-- SELECT (insert) --" mode
+ call feedkeys("\<F8>", 'xt!')
+ redraw!
+ call assert_match('^-- (insert) SELECT --', Screenline(&lines))
+ call assert_equal(['s', 1, 3, 2, 4], [mode(1), line('v'), col('v'), line('.'), col('.')])
+ call feedkeys("\<Esc>new ", 'x')
+ call assert_equal(['some short lines', 'of new test text'], getline(1, '$'))
+
+ sunmap <F1>
+ sunmap <F2>
+ call s:cleanupMaps()
+ set showmode&
+ %bw!
+endfunc
+
+" Test for <Cmd> mapping in operator-pending mode
+func Test_map_cmdkey_op_pending_mode()
+ new
+ call s:setupMaps()
+
+ call setline(1, ['some short lines', 'of test text'])
+ call feedkeys("d\<F4>", 'xt')
+ call assert_equal(['lines', 'of test text'], getline(1, '$'))
+ call assert_equal(['some short '], getreg('"', 1, 1))
+ " create a new undo point
+ let &undolevels = &undolevels
+
+ call feedkeys(".", 'xt')
+ call assert_equal(['test text'], getline(1, '$'))
+ call assert_equal(['lines', 'of '], getreg('"', 1, 1))
+ " create a new undo point
+ let &undolevels = &undolevels
+
+ call feedkeys("uu", 'xt')
+ call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
+
+ " error aborts operator-pending, operator not performed
+ call assert_fails('call feedkeys("d\<F6>", "xt")', 'E605:')
+ call assert_equal(['some short lines', 'of test text'], getline(1, '$'))
+
+ call feedkeys("\"bd\<F7>", 'xt')
+ call assert_equal(['soest text'], getline(1, '$'))
+ call assert_equal(['me short lines', 'of t'], getreg('b', 1, 1))
+
+ " startinsert aborts operator
+ call feedkeys("d\<F8>cc", 'xt')
+ call assert_equal(['soccest text'], getline(1, '$'))
+
+ call s:cleanupMaps()
+ %bw!
+endfunc
+
+" Test for <Cmd> mapping in insert mode
+func Test_map_cmdkey_insert_mode()
+ new
+ call s:setupMaps()
+
+ call setline(1, ['some short lines', 'of test text'])
+ " works the same as <C-O>w<C-O>w
+ call feedkeys("iindeed \<F4>little ", 'xt')
+ call assert_equal(['indeed some short little lines', 'of test text'], getline(1, '$'))
+ call assert_fails('call feedkeys("i\<F6> 2", "xt")', 'E605:')
+ call assert_equal(['indeed some short little 2 lines', 'of test text'], getline(1, '$'))
+
+ " Note when entering visual mode from InsertEnter autocmd, an async event,
+ " or a <Cmd> mapping, vim ends up in undocumented "INSERT VISUAL" mode.
+ call feedkeys("i\<F7>stuff ", 'xt')
+ call assert_equal(['indeed some short little 2 lines', 'of stuff test text'], getline(1, '$'))
+ call assert_equal(['v', 1, 3, 2, 9], [mode(1), line('v'), col('v'), line('.'), col('.')])
+
+ call feedkeys("\<F5>", 'xt')
+ call assert_equal(['deed some short little 2 lines', 'of stuff '], getreg('a', 1, 1))
+
+ " also works as part of abbreviation
+ abbr foo <Cmd>let g:y = 17<CR>bar
+ exe "normal i\<space>foo "
+ call assert_equal(17, g:y)
+ call assert_equal('in bar deed some short little 2 lines', getline(1))
+ unabbr foo
+
+ " :startinsert does nothing
+ call setline(1, 'foo bar')
+ call feedkeys("ggi\<F8>vim", 'xt')
+ call assert_equal('vimfoo bar', getline(1))
+
+ " :stopinsert works
+ call feedkeys("ggi\<F9>Abc", 'xt')
+ call assert_equal('vimfoo barbc', getline(1))
+
+ call s:cleanupMaps()
+ %bw!
+endfunc
+
+" Test for <Cmd> mapping in insert-completion mode
+func Test_map_cmdkey_insert_complete_mode()
+ new
+ call s:setupMaps()
+
+ call setline(1, 'some short lines')
+ call feedkeys("os\<C-X>\<C-N>\<F3>\<C-N> ", 'xt')
+ call assert_equal('ic', m)
+ call assert_equal(['some short lines', 'short '], getline(1, '$'))
+
+ call s:cleanupMaps()
+ %bw!
+endfunc
+
+" Test for <Cmd> mapping in cmdline mode
+func Test_map_cmdkey_cmdline_mode()
+ new
+ call s:setupMaps()
+
+ call setline(1, ['some short lines', 'of test text'])
+ let x = 0
+ call feedkeys(":let x\<F3>= 10\r", 'xt')
+ call assert_equal('c', m)
+ call assert_equal(10, x)
+
+ " exception doesn't leave cmdline mode
+ call assert_fails('call feedkeys(":let x\<F6>= 20\r", "xt")', 'E605:')
+ call assert_equal(20, x)
+
+ " move cursor in the buffer from cmdline mode
+ call feedkeys(":let x\<F4>= 30\r", 'xt')
+ call assert_equal(30, x)
+ call assert_equal(12, col('.'))
+
+ " :startinsert takes effect after leaving cmdline mode
+ call feedkeys(":let x\<F8>= 40\rnew ", 'xt')
+ call assert_equal(40, x)
+ call assert_equal('some short new lines', getline(1))
+
+ call s:cleanupMaps()
+ %bw!
+endfunc
+
func Test_map_cmdkey_redo()
func SelectDash()
call search('^---\n\zs', 'bcW')
@@ -1002,6 +1466,24 @@ func Test_map_cmdkey_redo()
call delete('Xcmdtext')
delfunc SelectDash
ounmap i-
+
+ new
+ call setline(1, 'aaa bbb ccc ddd')
+
+ " command can contain special keys
+ onoremap ix <Cmd>let g:foo ..= '…'<Bar>normal! <C-Right><CR>
+ let g:foo = ''
+ call feedkeys('0dix.', 'xt')
+ call assert_equal('……', g:foo)
+ call assert_equal('ccc ddd', getline(1))
+ unlet g:foo
+
+ " command line ending in "0" is handled without errors
+ onoremap ix <Cmd>eval 0<CR>
+ call feedkeys('dix.', 'xt')
+
+ ounmap ix
+ bwipe!
endfunc
" Test for using <script> with a map to remap characters in rhs
diff --git a/test/old/testdir/test_normal.vim b/test/old/testdir/test_normal.vim
index 330a16dffb..23baebb78c 100644
--- a/test/old/testdir/test_normal.vim
+++ b/test/old/testdir/test_normal.vim
@@ -3648,11 +3648,32 @@ func Test_horiz_motion()
bwipe!
endfunc
-" Test for using a : command in operator pending mode
+" Test for using a ":" command in operator pending mode
func Test_normal_colon_op()
new
call setline(1, ['one', 'two'])
call assert_beeps("normal! Gc:d\<CR>")
+ call assert_equal(['one'], getline(1, '$'))
+
+ call setline(1, ['one…two…three!'])
+ normal! $
+ " Using ":" as a movement is characterwise exclusive
+ call feedkeys("d:normal! F…\<CR>", 'xt')
+ call assert_equal(['one…two!'], getline(1, '$'))
+ " Check that redoing a command with 0x80 bytes works
+ call feedkeys('.', 'xt')
+ call assert_equal(['one!'], getline(1, '$'))
+
+ call setline(1, ['one', 'two', 'three', 'four', 'five'])
+ " Add this to the command history
+ call feedkeys(":normal! G0\<CR>", 'xt')
+ " Use :normal! with control characters in operator pending mode
+ call feedkeys("d:normal! \<C-V>\<C-P>\<C-V>\<C-P>\<CR>", 'xt')
+ call assert_equal(['one', 'two', 'five'], getline(1, '$'))
+ " Check that redoing a command with control characters works
+ call feedkeys('.', 'xt')
+ call assert_equal(['five'], getline(1, '$'))
+
bwipe!
endfunc
@@ -3972,4 +3993,22 @@ func Test_mouse_shape_after_cancelling_gr()
call delete('Xmouseshapes')
endfunc
+" Test that "j" does not skip lines when scrolling below botline and
+" 'foldmethod' is not "manual".
+func Test_normal_j_below_botline()
+ CheckScreendump
+
+ let lines =<< trim END
+ set number foldmethod=diff scrolloff=0
+ call setline(1, map(range(1, 9), 'repeat(v:val, 200)'))
+ norm Lj
+ END
+ call writefile(lines, 'XNormalJBelowBotline', 'D')
+ let buf = RunVimInTerminal('-S XNormalJBelowBotline', #{rows: 19, cols: 40})
+
+ call VerifyScreenDump(buf, 'Test_normal_j_below_botline', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_python2.vim b/test/old/testdir/test_python2.vim
deleted file mode 100644
index f21eb2c128..0000000000
--- a/test/old/testdir/test_python2.vim
+++ /dev/null
@@ -1,195 +0,0 @@
-" Test for python 2 commands.
-" TODO: move tests from test86.in here.
-
-source check.vim
-CheckFeature python
-
-func Test_pydo()
- " Check deleting lines does not trigger ml_get error.
- py import vim
- new
- call setline(1, ['one', 'two', 'three'])
- pydo vim.command("%d_")
- bwipe!
-
- " Disabled until neovim/neovim#8554 is resolved
- if 0
- " Check switching to another buffer does not trigger ml_get error.
- new
- let wincount = winnr('$')
- call setline(1, ['one', 'two', 'three'])
- pydo vim.command("new")
- call assert_equal(wincount + 1, winnr('$'))
- bwipe!
- bwipe!
- endif
-endfunc
-
-func Test_set_cursor()
- " Check that setting the cursor position works.
- py import vim
- new
- call setline(1, ['first line', 'second line'])
- normal gg
- pydo vim.current.window.cursor = (1, 5)
- call assert_equal([1, 6], [line('.'), col('.')])
-
- " Check that movement after setting cursor position keeps current column.
- normal j
- call assert_equal([2, 6], [line('.'), col('.')])
-endfunc
-
-func Test_vim_function()
- throw 'Skipped: Nvim does not support vim.bindeval()'
- " Check creating vim.Function object
- py import vim
-
- func s:foo()
- return matchstr(expand('<sfile>'), '<SNR>\zs\d\+_foo$')
- endfunc
- let name = '<SNR>' . s:foo()
-
- try
- py f = vim.bindeval('function("s:foo")')
- call assert_equal(name, pyeval('f.name'))
- catch
- call assert_false(v:exception)
- endtry
-
- try
- py f = vim.Function('\x80\xfdR' + vim.eval('s:foo()'))
- call assert_equal(name, 'f.name'->pyeval())
- catch
- call assert_false(v:exception)
- endtry
-
- py del f
- delfunc s:foo
-endfunc
-
-func Test_skipped_python_command_does_not_affect_pyxversion()
- set pyxversion=0
- if 0
- python import vim
- endif
- call assert_equal(0, &pyxversion) " This assertion would have failed with Vim 8.0.0251. (pyxversion was introduced in 8.0.0251.)
-endfunc
-
-func _SetUpHiddenBuffer()
- py import vim
- new
- edit hidden
- setlocal bufhidden=hide
-
- enew
- let lnum = 0
- while lnum < 10
- call append( 1, string( lnum ) )
- let lnum = lnum + 1
- endwhile
- normal G
-
- call assert_equal( line( '.' ), 11 )
-endfunc
-
-func _CleanUpHiddenBuffer()
- bwipe! hidden
- bwipe!
-endfunc
-
-func Test_Write_To_HiddenBuffer_Does_Not_Fix_Cursor_Clear()
- call _SetUpHiddenBuffer()
- py vim.buffers[ int( vim.eval( 'bufnr("hidden")' ) ) ][:] = None
- call assert_equal( line( '.' ), 11 )
- call _CleanUpHiddenBuffer()
-endfunc
-
-func Test_Write_To_HiddenBuffer_Does_Not_Fix_Cursor_List()
- call _SetUpHiddenBuffer()
- py vim.buffers[ int( vim.eval( 'bufnr("hidden")' ) ) ][:] = [ 'test' ]
- call assert_equal( line( '.' ), 11 )
- call _CleanUpHiddenBuffer()
-endfunc
-
-func Test_Write_To_HiddenBuffer_Does_Not_Fix_Cursor_Str()
- call _SetUpHiddenBuffer()
- py vim.buffers[ int( vim.eval( 'bufnr("hidden")' ) ) ][0] = 'test'
- call assert_equal( line( '.' ), 11 )
- call _CleanUpHiddenBuffer()
-endfunc
-
-func Test_Write_To_HiddenBuffer_Does_Not_Fix_Cursor_ClearLine()
- call _SetUpHiddenBuffer()
- py vim.buffers[ int( vim.eval( 'bufnr("hidden")' ) ) ][0] = None
- call assert_equal( line( '.' ), 11 )
- call _CleanUpHiddenBuffer()
-endfunc
-
-func _SetUpVisibleBuffer()
- py import vim
- new
- let lnum = 0
- while lnum < 10
- call append( 1, string( lnum ) )
- let lnum = lnum + 1
- endwhile
- normal G
- call assert_equal( line( '.' ), 11 )
-endfunc
-
-func Test_Write_To_Current_Buffer_Fixes_Cursor_Clear()
- call _SetUpVisibleBuffer()
-
- py vim.current.buffer[:] = None
- call assert_equal( line( '.' ), 1 )
-
- bwipe!
-endfunc
-
-func Test_Write_To_Current_Buffer_Fixes_Cursor_List()
- call _SetUpVisibleBuffer()
-
- py vim.current.buffer[:] = [ 'test' ]
- call assert_equal( line( '.' ), 1 )
-
- bwipe!
-endfunction
-
-func Test_Write_To_Current_Buffer_Fixes_Cursor_Str()
- call _SetUpVisibleBuffer()
-
- py vim.current.buffer[-1] = None
- call assert_equal( line( '.' ), 10 )
-
- bwipe!
-endfunction
-
-func Test_Catch_Exception_Message()
- try
- py raise RuntimeError( 'TEST' )
- catch /.*/
- call assert_match('^Vim(.*):.*RuntimeError: TEST$', v:exception )
- endtry
-endfunc
-
-" Test for various heredoc syntax
-func Test_python_heredoc()
- python << END
-s='A'
-END
- python <<
-s+='B'
-.
- python << trim END
- s+='C'
- END
- python << trim
- s+='D'
- .
- python << trim eof
- s+='E'
- eof
- call assert_equal('ABCDE', pyxeval('s'))
-endfunc
-
-" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_pyx2.vim b/test/old/testdir/test_pyx2.vim
deleted file mode 100644
index 74f4b187f0..0000000000
--- a/test/old/testdir/test_pyx2.vim
+++ /dev/null
@@ -1,103 +0,0 @@
-" Test for pyx* commands and functions with Python 2.
-
-source check.vim
-CheckFeature python
-set pyx=2
-
-let s:py2pattern = '^2\.[0-7]\.\d\+'
-let s:py3pattern = '^3\.\d\+\.\d\+'
-
-
-func Test_has_pythonx()
- call assert_true(has('pythonx'))
-endfunc
-
-
-func Test_pyx()
- redir => var
- pyx << trim EOF
- import sys
- print(sys.version)
- EOF
- redir END
- call assert_match(s:py2pattern, split(var)[0])
-endfunc
-
-
-func Test_pyxdo()
- pyx import sys
- enew
- pyxdo return sys.version.split("\n")[0]
- call assert_match(s:py2pattern, split(getline('.'))[0])
-endfunc
-
-
-func Test_pyxeval()
- pyx import sys
- call assert_match(s:py2pattern, split('sys.version'->pyxeval())[0])
-endfunc
-
-
-func Test_pyxfile()
- " No special comments nor shebangs
- redir => var
- pyxfile pyxfile/pyx.py
- redir END
- call assert_match(s:py2pattern, split(var)[0])
-
- " Python 2 special comment
- redir => var
- pyxfile pyxfile/py2_magic.py
- redir END
- call assert_match(s:py2pattern, split(var)[0])
-
- " Python 2 shebang
- redir => var
- pyxfile pyxfile/py2_shebang.py
- redir END
- call assert_match(s:py2pattern, split(var)[0])
-
- if has('python3')
- " Python 3 special comment
- redir => var
- pyxfile pyxfile/py3_magic.py
- redir END
- call assert_match(s:py3pattern, split(var)[0])
-
- " Python 3 shebang
- redir => var
- pyxfile pyxfile/py3_shebang.py
- redir END
- call assert_match(s:py3pattern, split(var)[0])
- endif
-endfunc
-
-func Test_Catch_Exception_Message()
- try
- pyx raise RuntimeError( 'TEST' )
- catch /.*/
- call assert_match('^Vim(.*):.*RuntimeError: TEST$', v:exception )
- endtry
-endfunc
-
-" Test for various heredoc syntaxes
-func Test_pyx2_heredoc()
- pyx << END
-result='A'
-END
- pyx <<
-result+='B'
-.
- pyx << trim END
- result+='C'
- END
- pyx << trim
- result+='D'
- .
- pyx << trim eof
- result+='E'
- eof
- call assert_equal('ABCDE', pyxeval('result'))
-endfunc
-
-" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_scroll_opt.vim b/test/old/testdir/test_scroll_opt.vim
index 1d09c863eb..5ac80764b5 100644
--- a/test/old/testdir/test_scroll_opt.vim
+++ b/test/old/testdir/test_scroll_opt.vim
@@ -257,11 +257,14 @@ func Test_smoothscroll_wrap_scrolloff_zero()
call term_sendkeys(buf, "G")
call VerifyScreenDump(buf, 'Test_smooth_wrap_4', {})
- " moving cursor up right after the >>> marker - no need to show whole line
+ call term_sendkeys(buf, "4\<C-Y>G")
+ call VerifyScreenDump(buf, 'Test_smooth_wrap_4', {})
+
+ " moving cursor up right after the <<< marker - no need to show whole line
call term_sendkeys(buf, "2gj3l2k")
call VerifyScreenDump(buf, 'Test_smooth_wrap_5', {})
- " moving cursor up where the >>> marker is - whole top line shows
+ " moving cursor up where the <<< marker is - whole top line shows
call term_sendkeys(buf, "2j02k")
call VerifyScreenDump(buf, 'Test_smooth_wrap_6', {})
@@ -323,11 +326,11 @@ func Test_smoothscroll_wrap_long_line()
call VerifyScreenDump(buf, 'Test_smooth_long_10', {})
" Test zt/zz/zb that they work properly when a long line is above it
- call term_sendkeys(buf, "zb")
+ call term_sendkeys(buf, "zt")
call VerifyScreenDump(buf, 'Test_smooth_long_11', {})
call term_sendkeys(buf, "zz")
call VerifyScreenDump(buf, 'Test_smooth_long_12', {})
- call term_sendkeys(buf, "zt")
+ call term_sendkeys(buf, "zb")
call VerifyScreenDump(buf, 'Test_smooth_long_13', {})
" Repeat the step and move the cursor down again.
@@ -335,9 +338,12 @@ func Test_smoothscroll_wrap_long_line()
" than one window. Note that the cursor is at the bottom this time because
" Vim prefers to do so if we are scrolling a few lines only.
call term_sendkeys(buf, ":call setline(1, ['one', 'two', 'Line' .. (' with lots of text'->repeat(10)) .. ' end', 'four'])\<CR>")
+ " Currently visible lines were replaced, test that the lines and cursor
+ " are correctly displayed.
+ call VerifyScreenDump(buf, 'Test_smooth_long_14', {})
call term_sendkeys(buf, "3Gzt")
call term_sendkeys(buf, "j")
- call VerifyScreenDump(buf, 'Test_smooth_long_14', {})
+ call VerifyScreenDump(buf, 'Test_smooth_long_15', {})
" Repeat the step but this time start it when the line is smooth-scrolled by
" one line. This tests that the offset calculation is still correct and
@@ -345,7 +351,7 @@ func Test_smoothscroll_wrap_long_line()
" screen.
call term_sendkeys(buf, "3Gzt")
call term_sendkeys(buf, "\<C-E>j")
- call VerifyScreenDump(buf, 'Test_smooth_long_15', {})
+ call VerifyScreenDump(buf, 'Test_smooth_long_16', {})
call StopVimInTerminal(buf)
endfunc
@@ -416,6 +422,17 @@ func Test_smoothscroll_cursor_position()
exe "normal \<C-Y>"
call s:check_col_calc(1, 3, 41)
+ " Test "g0/g<Home>"
+ exe "normal gg\<C-E>"
+ norm $gkg0
+ call s:check_col_calc(1, 2, 21)
+
+ " Test moving the cursor behind the <<< display with 'virtualedit'
+ set virtualedit=all
+ exe "normal \<C-E>3lgkh"
+ call s:check_col_calc(3, 2, 23)
+ set virtualedit&
+
normal gg3l
exe "normal \<C-E>"
@@ -484,6 +501,16 @@ func Test_smoothscroll_cursor_position()
call s:check_col_calc(1, 3, 37)
normal gg
+ " Test list + listchars "precedes", where there is always 1 overlap
+ " regardless of number and cpo-=n.
+ setl number list listchars=precedes:< cpo-=n
+ call s:check_col_calc(5, 1, 1)
+ exe "normal 3|\<C-E>h"
+ call s:check_col_calc(6, 1, 18)
+ norm h
+ call s:check_col_calc(5, 2, 17)
+ normal gg
+
bwipe!
endfunc
@@ -638,4 +665,73 @@ func Test_smoothscroll_ins_lines()
call StopVimInTerminal(buf)
endfunc
+" this placed the cursor in the command line
+func Test_smoothscroll_cursormoved_line()
+ CheckScreendump
+
+ let lines =<< trim END
+ set smoothscroll
+ call setline(1, [
+ \'',
+ \'_'->repeat(&lines * &columns),
+ \(('_')->repeat(&columns - 2) .. 'xxx')->repeat(2)
+ \])
+ autocmd CursorMoved * eval [line('w0'), line('w$')]
+ call search('xxx')
+ END
+ call writefile(lines, 'XSmoothCursorMovedLine', 'D')
+ let buf = RunVimInTerminal('-S XSmoothCursorMovedLine', #{rows: 6})
+
+ call VerifyScreenDump(buf, 'Test_smooth_cursormoved_line', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+func Test_smoothscroll_eob()
+ CheckScreendump
+
+ let lines =<< trim END
+ set smoothscroll
+ call setline(1, ['']->repeat(100))
+ norm G
+ END
+ call writefile(lines, 'XSmoothEob', 'D')
+ let buf = RunVimInTerminal('-S XSmoothEob', #{rows: 10})
+
+ " does not scroll halfway when scrolling to end of buffer
+ call VerifyScreenDump(buf, 'Test_smooth_eob_1', {})
+
+ " cursor is not placed below window
+ call term_sendkeys(buf, ":call setline(92, 'a'->repeat(100))\<CR>\<C-B>G")
+ call VerifyScreenDump(buf, 'Test_smooth_eob_2', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+" skipcol should not reset when doing incremental search on the same word
+func Test_smoothscroll_incsearch()
+ CheckScreendump
+
+ let lines =<< trim END
+ set smoothscroll number scrolloff=0 incsearch
+ call setline(1, repeat([''], 20))
+ call setline(11, repeat('a', 100))
+ call setline(14, 'bbbb')
+ END
+ call writefile(lines, 'XSmoothIncsearch', 'D')
+ let buf = RunVimInTerminal('-S XSmoothIncsearch', #{rows: 8, cols:40})
+
+ call term_sendkeys(buf, "/b")
+ call VerifyScreenDump(buf, 'Test_smooth_incsearch_1', {})
+ call term_sendkeys(buf, "b")
+ call VerifyScreenDump(buf, 'Test_smooth_incsearch_2', {})
+ call term_sendkeys(buf, "b")
+ call VerifyScreenDump(buf, 'Test_smooth_incsearch_3', {})
+ call term_sendkeys(buf, "b")
+ call VerifyScreenDump(buf, 'Test_smooth_incsearch_4', {})
+ call term_sendkeys(buf, "\<CR>")
+
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_spell.vim b/test/old/testdir/test_spell.vim
index c840e834b9..b0b2668758 100644
--- a/test/old/testdir/test_spell.vim
+++ b/test/old/testdir/test_spell.vim
@@ -972,28 +972,83 @@ func Test_spell_screendump()
\ ])
set spell spelllang=en_nz
END
- call writefile(lines, 'XtestSpell')
+ call writefile(lines, 'XtestSpell', 'D')
let buf = RunVimInTerminal('-S XtestSpell', {'rows': 8})
call VerifyScreenDump(buf, 'Test_spell_1', {})
+ " clean up
+ call StopVimInTerminal(buf)
+endfunc
+
+func Test_spell_screendump_spellcap()
+ CheckScreendump
+
let lines =<< trim END
call setline(1, [
- \ "This is some text without any spell errors. Everything",
- \ "should just be black, nothing wrong here.",
+ \ " This line has a sepll error. and missing caps and trailing spaces. ",
+ \ "another missing cap here.",
\ "",
- \ "This line has a sepll error. and missing caps.",
- \ "And and this is the the duplication.",
- \ "with missing caps here.",
+ \ "and here.",
+ \ " ",
+ \ "and here."
\ ])
- set spell spelllang=en_nz
+ set spell spelllang=en
END
- call writefile(lines, 'XtestSpell')
- let buf = RunVimInTerminal('-S XtestSpell', {'rows': 8})
- call VerifyScreenDump(buf, 'Test_spell_1', {})
+ call writefile(lines, 'XtestSpellCap', 'D')
+ let buf = RunVimInTerminal('-S XtestSpellCap', {'rows': 8})
+ call VerifyScreenDump(buf, 'Test_spell_2', {})
+
+ " After adding word missing Cap in next line is updated
+ call term_sendkeys(buf, "3GANot\<Esc>")
+ call VerifyScreenDump(buf, 'Test_spell_3', {})
+
+ " Deleting a full stop removes missing Cap in next line
+ call term_sendkeys(buf, "5Gdd\<C-L>k$x")
+ call VerifyScreenDump(buf, 'Test_spell_4', {})
+
+ " Undo also updates the next line (go to command line to remove message)
+ call term_sendkeys(buf, "u:\<Esc>")
+ call VerifyScreenDump(buf, 'Test_spell_5', {})
+
+ " Folding an empty line does not remove Cap in next line
+ call term_sendkeys(buf, "uzfk:\<Esc>")
+ call VerifyScreenDump(buf, 'Test_spell_6', {})
+
+ " Folding the end of a sentence does not remove Cap in next line
+ " and editing a line does not remove Cap in current line
+ call term_sendkeys(buf, "Jzfkk$x")
+ call VerifyScreenDump(buf, 'Test_spell_7', {})
+
+ " Cap is correctly applied in the first row of a window
+ call term_sendkeys(buf, "\<C-E>\<C-L>")
+ call VerifyScreenDump(buf, 'Test_spell_8', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+endfunc
+
+func Test_spell_compatible()
+ CheckScreendump
+
+ let lines =<< trim END
+ call setline(1, [
+ \ "test "->repeat(20),
+ \ "",
+ \ "end",
+ \ ])
+ set spell cpo+=$
+ END
+ call writefile(lines, 'XtestSpellComp', 'D')
+ let buf = RunVimInTerminal('-S XtestSpellComp', {'rows': 8})
+
+ call term_sendkeys(buf, "51|C")
+ call VerifyScreenDump(buf, 'Test_spell_compatible_1', {})
+
+ call term_sendkeys(buf, "x")
+ call VerifyScreenDump(buf, 'Test_spell_compatible_2', {})
" clean up
call StopVimInTerminal(buf)
- call delete('XtestSpell')
endfunc
let g:test_data_aff1 = [
diff --git a/test/old/testdir/test_utf8.vim b/test/old/testdir/test_utf8.vim
index e5f6d68720..00b060a9e2 100644
--- a/test/old/testdir/test_utf8.vim
+++ b/test/old/testdir/test_utf8.vim
@@ -29,8 +29,10 @@ func Test_strchars()
call assert_equal(exp[i], strcharlen(inp[i]))
endfor
- call assert_fails("let v=strchars('abc', [])", 'E745:')
- call assert_fails("let v=strchars('abc', 2)", 'E1023:')
+ call assert_fails("call strchars('abc', 2)", ['E1023:', 'E1023:'])
+ call assert_fails("call strchars('abc', -1)", ['E1023:', 'E1023:'])
+ call assert_fails("call strchars('abc', {})", ['E728:', 'E728:'])
+ call assert_fails("call strchars('abc', [])", ['E745:', 'E745:'])
endfunc
" Test for customlist completion